我有一些关于同步关键字的用法和意义的问题。
synchronized关键字有什么意义? 什么时候应该同步方法? 它在程序上和逻辑上意味着什么?
我有一些关于同步关键字的用法和意义的问题。
synchronized关键字有什么意义? 什么时候应该同步方法? 它在程序上和逻辑上意味着什么?
当前回答
Synchronized意味着在多线程环境中,具有同步方法/块的对象不允许两个线程同时访问Synchronized方法/块的代码。这意味着一个线程不能读取,而另一个线程更新它。
第二个线程将等待第一个线程完成它的执行。开销是速度,但好处是保证了数据的一致性。
如果你的应用程序是单线程的,同步块并不能带来什么好处。
其他回答
Synchronized意味着在多线程环境中,具有同步方法/块的对象不允许两个线程同时访问Synchronized方法/块的代码。这意味着一个线程不能读取,而另一个线程更新它。
第二个线程将等待第一个线程完成它的执行。开销是速度,但好处是保证了数据的一致性。
如果你的应用程序是单线程的,同步块并不能带来什么好处。
synchronized是Java中的关键字,用于在多线程环境中使发生在关系之前,以避免内存不一致和线程干扰错误。
What the other answers are missing is one important aspect: memory barriers. Thread synchronization basically consists of two parts: serialization and visibility. I advise everyone to google for "jvm memory barrier", as it is a non-trivial and extremely important topic (if you modify shared data accessed by multiple threads). Having done that, I advise looking at java.util.concurrent package's classes that help to avoid using explicit synchronization, which in turn helps keeping programs simple and efficient, maybe even preventing deadlocks.
ConcurrentLinkedDeque就是这样一个例子。与命令模式一起,它允许通过将命令填充到并发队列中来创建高效的工作线程——不需要显式同步,不可能发生死锁,不需要显式sleep(),只需通过调用take()轮询队列。
简而言之:“内存同步”隐式地发生在线程启动、线程结束、读取volatile变量、解锁监视器(留下同步块/函数)等时候。这种“同步”影响(在某种意义上“刷新”)在该特定操作之前完成的所有写操作。在前面提到的ConcurrentLinkedDeque的情况下,文档“说”:
内存一致性影响:与其他并发集合一样, 对象放入线程之前的操作 ConcurrentLinkedDeque访问之后的happens -before操作 或者从另一个ConcurrentLinkedDeque中删除该元素 线程。
这种隐式行为在某种程度上是有害的,因为大多数没有太多经验的Java程序员会因此而得过其实。然后突然被这个线程绊倒,因为Java在生产中没有做它“应该”做的事情,因为有不同的工作负载——并且很难测试并发性问题。
你可以把它想象成一个转门,就像你在足球场看到的那样。有平行的人群想要进入,但在旋转门他们是“同步的”。一次只能有一个人通过。所有想要通过的人都可以,但他们可能要等到他们能够通过。
概述
Java中的Synchronized关键字与线程安全有关,也就是说,当多个线程读或写同一个变量时。 这可以直接发生(通过访问相同的变量)或间接发生(通过使用使用访问相同变量的另一个类的类)。
synchronized关键字用于定义一个代码块,其中多个线程可以以安全的方式访问同一个变量。
更深层次的
从语法上看,synchronized关键字接受一个Object作为它的参数(称为锁对象),然后后面跟着一个{block of code}。
When execution encounters this keyword, the current thread tries to "lock/acquire/own" (take your pick) the lock object and execute the associated block of code after the lock has been acquired. Any writes to variables inside the synchronized code block are guaranteed to be visible to every other thread that similarly executes code inside a synchronized code block using the same lock object. Only one thread at a time can hold the lock, during which time all other threads trying to acquire the same lock object will wait (pause their execution). The lock will be released when execution exits the synchronized code block.
同步的方法:
将synchronized关键字添加到方法定义中等于将整个方法体包装在同步代码块中,锁对象为this(对于实例方法)和ClassInQuestion.getClass()(对于类方法)。
—实例方法是没有静态关键字的方法。 —类方法是具有静态关键字的方法。
技术
如果没有同步,就无法保证以何种顺序进行读写,可能会给变量留下垃圾。 (例如,一个变量可能由一个线程写入一半的比特,另一个线程写入一半的比特,使变量处于两个线程都没有尝试写入的状态,而是两者结合在一起的混乱状态。)
在另一个线程读取之前(时钟时间)完成一个线程的写操作是不够的,因为硬件可能已经缓存了变量的值,读取线程将看到缓存的值,而不是写入它的值。
结论
因此,在Java的情况下,您必须遵循Java内存模型,以确保线程错误不会发生。 换句话说:在底层使用同步、原子操作或为您使用它们的类。
来源 http://docs.oracle.com/javase/specs/jls/se8/html/index.html Java®语言规范,2015-02-13