1.上代码:
package com.finger.gates.myapplication;
public class JavaStudy {
private static Thread a, b;
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
a = new Thread(r, "1");
b = new Thread(r, "2");
a.start();
//执行方法过程中 当前对象被锁定
b.start(); }
static class MyRunnable implements Runnable {
@Override
public void run() {
if (Thread.currentThread().getName().equals("1")) { synchronized (a) {
try {
Thread.sleep(500);
} catch (InterruptedException e) { e.printStackTrace(); }
synchronized (b) {
System.out.println("11111");
} } }
if (Thread.currentThread().getName().equals("2")) {
synchronized (b) {
try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); }
synchronized (a) {
System.out.println("2222"); } } } } }}
2.分析
看myrunner类。一开始定义了两个thread,然后执行方法。当线程1执行的时候先锁住a,然后让他去休眠,再去锁住b;同时线程2做线程1相反的事情。然而
synchronized的效果是,执行方法过程中,当前对象被锁定
所以在线程1休眠完了之后要去锁住线程2的时候,发现2已经被另一个线程锁定了;另一面线程2也遇到了相同的情况,两边都不肯放手,就这样死耗着,这就造成了死锁。
3.解决方案
为了避免这种情况的发生,我们在加锁的时候,尽量选在粒度较大的位置,比如说直接放在run()方法上,
_public synchronised void run() _
这样就可以了,当然如果场景比较特殊则再议。
4.用途
据说一般在写系统级应用的情况下才接触的比较多,比如说写一个数据库的时候,要控制只读,只写等。
5.拓展
比较形象的理解是 五个哲学家吃饭的故事