自从我开始用 Java 编程以来,我一直在想这个问题(大约一两年)。在C中,我们必须知道不同的方法才能正确避免线程之间的死锁,因此同步方法之间有更多的选择。
那么Java呢?当我们进行同步时,如何避免线程陷入死锁情况?它的内部是如何运作的?是否因为我们在比 C(或 C++)更高的级别上进行同步而避免了死锁?有没有关于java中的死锁和同步的文档?
Since I've started programming in Java I have been wondering this (about a year or two). In C, we must know the different method to correctly avoid deadlock between thread and thus there is much more choice between synchronization method.
So what about Java? When we synchronize, how does it avoid putting thread in deadlock situation? How does it work internally? Does the deadlock are avoided because we synchronized on higher level than in C ( or C++)? Any documentation about deadlock and synchronization in java?
发布评论
评论(7)
在底层,它在字节码级别使用两个操作码
monitorenter
和monitorexit
,它们在 JVM 全局级别获取/释放对象引用上的锁。我强烈建议您阅读 Java虚拟机如何进行线程同步。Under the hood it is using two opcodes
monitorenter
andmonitorexit
at the byte code level which acquire/release locks on an object reference at a JVM global level. I highly recommend you read How the Java virtual machine performs thread synchronization.我们在多线程代码中遇到的主要问题是共享数据,我同意并发并行化进程的目的,并且“经常”发生在并行化处理期间线程需要访问以读取/写入共享数据。
java的synchronized关键字允许以下操作:
它告诉JVM在对象或同步代码片段的监视器上放置一个锁,这使其能够独占访问该部分代码或对象。
这是一个单例的例子:
这个单例不是线程安全,如果一个线程试图获取一个实例,而另一个线程也试图做同样的事情(竞争条件),那么可能会发生在此之前第一个线程完成了实例的创建,第二个线程已经可以访问 getInstance() 方法并创建了他自己的 Singleton 实例,这意味着在 T 时间内我们应该有两个实例Singleton(当时称为multiton)。
为了解决这个问题,我们必须同步单例的创建行为,这可以通过
INSTANCE
本身的 if 语句上方的关键字synchronized
来完成:结果是第一个线程请求 Singleton 实例,并且在创建期间,JVM 将在实例的监视器上加锁,拒绝对实例的任何访问,直到线程 1 完成其请求。
也有不同的方法可以实现这一点,前面引用的书是一个很好的学习来源,javadoc也是。
The main problem(s) we meet with a multithreaded code is sharing data, and I agree with, the purpose of concurency parallizing process and it happens "ofently" that during parallalized processing that threads need accessing for read/write on shared data.
The java synchronized keyword permits the following:
It tells the JVM to put a lock on the monitor of the object or the piece of the synchronized code, which gives it exclusive access to that part of code or object.
Here's an example of a Singleton:
This Singleton is not thread safe, if a thread is trying to get an instance while another is also trying to do the same (race condition) it may happen that before that the thread number one finishes the creation of the instance the second has already had access to the
getInstance()
method and created his own instance of the Singleton which means that at a T time we should have two instances of the Singleton (called multiton at that time).To solve this problem we have to synchronize the creational behaviour of the singleton, this may be done by the keyword
synchronized
above the if statement on theINSTANCE
itself:The result is when the first thread asks the Singleton instance and during creation time, the JVM will put a lock on the monitor of the INSTANCE denying any access to the INSTANCE until thread one finished its request.
There are diffrent ways to achieve that as well, the book cited before is an excellent source of learning, javadoc also.
Java 中的同步实际上并不比 C 中的容易多少。从语法上来看,它更容易,因为对于互斥体,您所需要做的就是将方法声明为同步或使用,
而在 C/C++ 中,您可以要使用操作系统特定的函数来使用互斥锁,或者您必须使用 Boost 库。
但关于死锁的陷阱与任何语言基本上都是相同的。
Synchronization isn't really that much easier in Java than in C. Syntactically it's easier, because all you need to do for a mutex is declare a method as synchronized or use
Whereas in C/C++, you have to use operating-system-specific functions to use a mutex, or you have to use the Boost library.
But the pitfalls about deadlock are all basically the same as in any language.
简短回答:
同步
方法和lock
块使用监视器来锁定锁定对象的信号量在方法或块的持续时间内。Java 语言本身并不能防止死锁。作为程序员,您需要确保以正确的顺序锁定/解锁对象以防止争用。
Short answers:
synchronized
methods andlock
blocks use a monitor that locks the semaphore of the locked object for the duration of the method or block.The Java language itself does not prevent deadlocks. That's up to you as the programmer to insure that objects are locked/unlocked in the correct order to prevent contention.
您还必须处理 Java 中的死锁。产生死锁的最简单方法是让一个线程在 A 上运行一个同步块,然后在 B 上运行另一个同步块,而另一个线程在 B 上执行一个同步块,然后在 A 上运行一个同步块
。阅读 有关并发的 Java 教程。 如果您想继续学习,请阅读Java 并发实践。
You also have to take care of deadlocks in Java. The easiest way to get a deadlock is to make one thread run a block synchronized on A, and then another block synchronized on B, while another thread executes a block synchronized on B, and then a block synchronized on A.
Read the Java tutorial about concurrency. And if you want to keep learning, read Java concurrency in practice.
您是否尝试过 google(Java 死锁)?第一个结果是这样的: http://download.oracle.com/javase/ tutorial/essential/concurrency/deadlock.html
在这里您可以看到,使用
synchronized
死锁仍然会发生,因为同步的设计初衷并不是为了防止死锁。Did you try google (Java Deadlock)? First result is this: http://download.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
There you can see that with
synchronized
deadlocks still occur, since synchronization is not designed to prevent those in the first place.我在上面看到了 Singleton 的一些问题。我认为这个类永远不会被创建。请考虑下面的代码。
I see some issue with Singleton above. I think that class will never be created. Please consider below code.