1、java对象的锁
java中的每个对象都有一个唯一的锁。在任何时刻,最多只允许一个线程拥有这把锁。当我们使用synchronized关键字时,锁的概念就会出现。
2、死锁示例
下面是容易出现死锁的示例参考代码,不建议使用在线 IDE 运行上述程序。建议使用javac命令编译之后使用java命令运行。
// Java program to illustrate Deadlock
// in multithreading.
class Util
{
// Util class to sleep a thread
static void sleep(long millis)
{
try
{
Thread.sleep(millis);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
// This class is shared by both threads
class Shared
{
// first synchronized method
synchronized void test1(Shared s2)
{
System.out.println("test1-begin");
Util.sleep(1000);
// taking object lock of s2 enters
// into test2 method
s2.test2();
System.out.println("test1-end");
}
// second synchronized method
synchronized void test2()
{
System.out.println("test2-begin");
Util.sleep(1000);
// taking object lock of s1 enters
// into test1 method
System.out.println("test2-end");
}
}
class Thread1 extends Thread
{
private Shared s1;
private Shared s2;
// constructor to initialize fields
public Thread1(Shared s1, Shared s2)
{
this.s1 = s1;
this.s2 = s2;
}
// run method to start a thread
@Override
public void run()
{
// taking object lock of s1 enters
// into test1 method
s1.test1(s2);
}
}
class Thread2 extends Thread
{
private Shared s1;
private Shared s2;
// constructor to initialize fields
public Thread2(Shared s1, Shared s2)
{
this.s1 = s1;
this.s2 = s2;
}
// run method to start a thread
@Override
public void run()
{
// taking object lock of s2
// enters into test2 method
s2.test1(s1);
}
}
public class Deadlock
{
public static void main(String[] args)
{
// creating one object
Shared s1 = new Shared();
// creating second object
Shared s2 = new Shared();
// creating first thread and starting it
Thread1 t1 = new Thread1(s1, s2);
t1.start();
// creating second thread and starting it
Thread2 t2 = new Thread2(s1, s2);
t2.start();
// sleeping main thread
Util.sleep(2000);
}
}
上面代码进行了那些操作?
3、查看死锁
在运行上一小节的代码之后,出现死锁时可以进入windows详细信息,可以看到两个java线程在运行。
我们可以再启动一个cmd窗口,运行jcmd $PID Thread.print命令,其中$PID是上图中的线程id。
我这里输入jcmd 53364 Thread.print之后回车,会看到输出明确说明发现一个死锁。
4、避免死锁
避免嵌套锁:这是死锁的主要原因。死锁主要发生在我们给多个线程加锁时。如果我们已经给了一个线程,请避免给多个线程加锁。
避免不必要的锁:我们应该只锁定那些需要的成员。不必要的锁定会导致死锁。
使用join:当一个线程正在等待另一个线程完成时出现死锁情况。如果发生这种情况,我们可以使用 Thread.join 以及您认为执行所需的最长时间。