自从我开始使用Java编程以来,我一直在想这个问题(大约一年或两年)。在C中,我们必须知道正确避免线程之间死锁的不同方法,因此在同步方法之间有更多的选择。
那么Java呢?当我们同步时,它如何避免将线程置于死锁状态?它在内部如何运作?死锁是否被避免,因为我们在更高级别上比在C(或C ++)中同步?有关java中死锁和同步的任何文档吗?
答案 0 :(得分:14)
在幕后,它在字节代码级别使用两个操作码monitorenter
和monitorexit
,它在JVM全局级别上获取/释放对象引用的锁定。我强烈建议您阅读How the Java virtual machine performs thread synchronization。
答案 1 :(得分:5)
我们遇到的多线程代码的主要问题是共享数据,我同意,concurency parallizing进程的目的并且“经常”发生在parallalized处理期间线程需要访问以进行读/写共享数据
java synchronized关键字允许以下内容:
它告诉JVM锁定对象的监视器或同步代码的一部分,这使它可以独占访问该部分代码或对象。
以下是Singleton的一个例子:
public class Singleton {
private Singleton INSTANCE;
private Singleton() {
}
public Singleton getInstance() {
if (null == INSTANCE) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
这个Singleton不是线程安全的,如果一个线程试图获取一个实例,而另一个也试图做同样的事情(竞争条件),那么在此之前线程第一个完成第二个实例的创建已经可以访问getInstance()
方法并创建了自己的Singleton实例,这意味着在T时刻我们应该有两个Singleton实例(当时称为multiton)。
要解决此问题,我们必须同步单例的创建行为,这可以通过synchronized
本身上if语句上方的关键字INSTANCE
来完成:
public class Singleton {
private Singleton INSTANCE;
private Singleton() {
}
public Singleton getInstance() {
synchronized (Singleton.class) {
if (null == INSTANCE) {
synchronized(Singleton.class) {
Singleton inst = new Singleton();
INSTANCE = inst;
}
}
}
return INSTANCE;
}
}
结果是当第一个线程询问Singleton实例并且在创建期间,JVM将锁定INSTANCE的监视器,拒绝任何对INSTANCE的访问,直到第一个线程完成其请求为止。
有不同的方法可以实现这一点,之前引用的书是一个很好的学习来源,javadoc也是。
答案 2 :(得分:1)
在Java中同步并不比在C中容易得多。语法它更容易,因为你需要为互斥锁做的只是将方法声明为synchronized或者使用
synchronized(someObject)
{
someCode();
}
在C / C ++中,您必须使用特定于操作系统的函数来使用互斥锁,否则您必须使用Boost库。
但是关于死锁的陷阱与任何语言基本相同。
答案 3 :(得分:1)
简答:
synchronized
方法和lock
块使用监视器,在方法持续时间内锁定锁定对象的信号量或阻止。
Java语言本身并不能防止死锁。这取决于你作为程序员,以确保以正确的顺序锁定/解锁对象以防止争用。
答案 4 :(得分:0)
您还必须处理Java中的死锁。获得死锁的最简单方法是让一个线程在A上同步运行一个块,然后在B上同步另一个块,而另一个线程执行在B上同步的块,然后在A上同步一个块。
阅读the Java tutorial about concurrency.如果您想继续学习,请阅读Java concurrency in practice。
答案 5 :(得分:0)
你试过google (Java Deadlock)吗?第一个结果是:http://download.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
在那里你可以看到,synchronized
仍然会出现死锁,因为同步并不是为了防止这些死锁。
答案 6 :(得分:0)
我在上面看到了Singleton的一些问题。我认为这个课永远不会被创造出来。请考虑以下代码。
public class Singleton {
private static Singleton INSTANCE;
private Singleton() { }
public static Singleton getInstance() {
synchronized (Singleton.class) {
if (null == INSTANCE) {
synchronized(Singleton.class) {
Singleton inst = new Singleton();
INSTANCE = inst;
}
}
}
return INSTANCE;
}
}