首页 > 代码库 > java synchronized 同一对象多实例线程安全

java synchronized 同一对象多实例线程安全

synchronized java 语言最简单的线程并发同步语法,上源码最快理解,

Resouce类表示并发资源

使用方法1.直接锁住某一个变量,如代码中的lock,注意这里lock必须为static的。如果不是static有什么后果?

public class Resource {
private static Object lock = new Object();


private Object unLock = new Object();


public void say() {
synchronized (unLock) {
System.out.println("come in unlock");
synchronized (lock) {
System.out.println("come in sleep");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}
}

方法2,在方法前加上synchroized关键字

public synchronized  void say() {
System.out.println("come in sleep");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}


方法3,锁住class类
package com.learn.bao.mutithread;


public class Resource {


public void say() {
synchronized (Resource.class) {
System.out.println("come in unlock");
System.out.println("come in sleep");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

现在依次说一下其中的原理。

使用synchroized方法前要明白,这个关键字它到底锁住的是什么资源。

在多线程中,如果Resouce对象只有一个,上面几种方法都是可以的。

比如 下面的代码,都是可以的

package com.learn.bao.mutithread;


public class TestThread extends Thread {
private Resource r;


public TestThread(Resource r) {
this.r = r;
}


@Override
public void run() {
r.say();
}
}


package com.learn.bao.mutithread;


public class Main {
public static void main(String[] args) {
Resource r = new Resource();
for (int i = 0; i < 3; i++) {
TestThread t = new TestThread(r);


t.start();
}
}
}

为什么可以,因为所有线程都共用了一个对象Resouce,只有一个实例,所以加上synchroized关键词一定是线程安全的。

但是下面情况怎么办?

package com.learn.bao.mutithread;


public class Main {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
Resource r = new Resource();
TestThread t = new TestThread(r);


t.start();

}
}

对于方法1来说如果lock不是静态变量就不能在线程中共享,所以也就无法实现线程安全,所以锁变量必须加上static关键字。

对于方法2由于锁的是Resource是对象本身,如果Resource有多个对象,自然无法实现线程安全,只能保证在同一个对象上是线程安全的,对于上面的情况就无法适用了。如果是多实例就需要手动加锁或者把方法改成静态。

方法3对于多实例和单实例而言都是安全的,因为它锁住的是class对象,在多线程中只有一份唯一的对象,所以是安全的,同static lock,这个也是我推荐的做法,代码比较简洁。

这里还要强调一下static synchroized静态同步方法它实际锁住的是Resouce这个类,这个类与他有多个实例无关,即使是new Resource().say(),强制创建新对象调用静态同步方法也还是线程安全的。

java synchronized 同一对象多实例线程安全