自从我开始用Java编程以来,我一直在想这件事(大约一两年)。在C中,我们必须知道正确避免线程间死锁的不同方法,因此在同步方法之间有更多的选择。
那么Java呢?当我们进行同步时,如何避免将线程置于死锁状态?它是如何在内部工作的?死锁的避免是因为我们在比C(或C++)更高的级别上进行了同步吗?在java中有关于死锁和同步的文档吗?
发布于 2011-07-05 22:42:05
在幕后,它在字节码级别使用两个操作码monitorenter和monitorexit,这两个操作码在JVM全局级别获取/释放对象引用上的锁。我强烈建议你阅读How the Java virtual machine performs thread synchronization。
发布于 2011-07-05 23:05:56
我们在多线程代码中遇到的主要问题是共享数据,我同意并发并行处理的目的,在并行处理期间,线程需要访问共享数据以进行读/写,这种情况“经常”发生。
java synchronized关键字允许执行以下操作:
它告诉JVM在对象或同步的代码片段的监视器上设置一个锁,这样就可以独占访问该部分代码或对象。
下面是一个单例的例子:
public class Singleton {
private Singleton INSTANCE;
private Singleton() {
}
public Singleton getInstance() {
if (null == INSTANCE) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}这个单例不是线程安全的,如果一个线程试图获取一个实例,而另一个线程也在尝试做同样的事情(竞争条件),那么在第一个线程完成实例的创建之前,第二个线程已经访问了getInstance()方法,并创建了他自己的单例实例,这意味着在T时间,我们应该有两个单例实例(当时称为multiton )。
为了解决这个问题,我们必须同步单例的创建行为,这可以通过INSTANCE本身的if语句上面的关键字synchronized来完成:
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将在该实例的监视器上放置一个锁,拒绝对该实例的任何访问,直到线程1完成其请求。
也有不同的方法来实现这一点,前面引用的这本书是一个很好的学习资源,javadoc也是。
发布于 2011-07-05 22:39:37
在Java中,同步并不比在C中容易得多。从语法上讲,它更简单,因为对于互斥来说,您所需要做的就是将一个方法声明为已同步或使用
synchronized(someObject)
{
someCode();
}而在C/C++中,您必须使用特定于操作系统的函数来使用互斥锁,或者必须使用Boost库。
但是死锁的陷阱基本上和任何语言中的一样。
https://stackoverflow.com/questions/6584355
复制相似问题