synchronized(非this对象)同步语句块
1. 将任意对象作为对象的监视器
1.1 在多个线程持有“对象监视器”为同一对象的前提下,同一时间只有一个线程可以执行synchronized(非this对象)同步代码块的代码。
1.1.1 Service
public class Service {
private String userName;
private String password;
private String aString = new String();
public void setUserInfo(String userName, String password){
try {
synchronized (aString){
System.out.println(Thread.currentThread().getName() + " in block");
this.userName = userName;
Thread.sleep(1000);
this.password = password;
System.out.println(Thread.currentThread().getName() + " out block");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1.1.2 ThreadA
public class ThreadA extends Thread {
private Service service;
public ThreadA(Service service){
super();
this.service = service;
}
@Override
public void run(){
service.setUserInfo("a", "aa");
}
}
1.1.3 ThreadB
public class ThreadB extends Thread {
private Service service;
public ThreadB(Service service){
super();
this.service = service;
}
@Override
public void run(){
service.setUserInfo("b", "bb");
}
}
1.1.4 Test
public class Test {
public static void main(String[] args) {
//A和B共用一个service这个对象,如果不共用一个service,会异步执行
Service service = new Service();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
}
}
1.1.5 运行结果
A in block
A out block
B in block
B out block
1.2 验证如果多个线程持有“对象监视器”不是同一对象,synchronized(非this对象)同步代码块将异步执行
1.2.1 修改Service类
public class Service {
private String userName;
private String password;
public void setUserInfo(String userName, String password){
try {
//aString是定义在setUsrInfo方法内的
String aString = new String();
synchronized (aString){
System.out.println(Thread.currentThread().getName() + " in block");
this.userName = userName;
Thread.sleep(1000);
this.password = password;
System.out.println(Thread.currentThread().getName() + " out block");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1.2.2 运行结果
其他类不变,结果如下
A in block
B in block
A out block
B out block
1.3验证synchronized(非this对象)块与synchronized方法是异步执行
1.3.1 修改Service类
public class Service {
private String userName;
private String password;
private String aString = new String();
public void setUserInfo(String userName, String password){
try {
synchronized (aString){
System.out.println(Thread.currentThread().getName() + " in block");
this.userName = userName;
Thread.sleep(1000);
this.password = password;
System.out.println(Thread.currentThread().getName() + " out block");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//与上面的synchronized (aString)是异步的
synchronized public void synchronizedMethod(){
System.out.println("synchronizedMethod begin");
System.out.println("synchronizedMethod end");
}
}
1.3.2 修改ThreadB类
public class ThreadB extends Thread {
private Service service;
public ThreadB(Service service){
super();
this.service = service;
}
@Override
public void run(){
service.synchronizedMethod();
}
}
1.3.3 运行结果
A in block
synchronizedMethod begin
synchronizedMethod end
A out block
从结果看是异步执行的
1.4 验证synchronized(a)和synchronized(b)是异步执行
1.4.1 修改Service 类
public class Service {
private String aString = new String();
private String bString = new String();
public void methodA() {
try {
synchronized (aString) {
System.out.println(Thread.currentThread().getName() + " in aString block");
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " out aString block");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void methodB() {
//和上面的synchronized (aString)是异步执行的
synchronized (bString) {
System.out.println(Thread.currentThread().getName() + " in bString block");
System.out.println(Thread.currentThread().getName() + " out bString block");
}
}
}
1.4.2 ThreadA
public class ThreadA extends Thread {
private Service service;
public ThreadA(Service service){
super();
this.service = service;
}
@Override
public void run(){
service.methodA();
}
}
1.4.3 ThreadB
public class ThreadB extends Thread {
private Service service;
public ThreadB(Service service){
super();
this.service = service;
}
@Override
public void run(){
service.methodB();
}
}
1.4.4 Test
public class Test {
public static void main(String[] args) {
Service service = new Service();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
}
}
1.4.5 运行结果
A in aString block
B in bString block
B out bString block
A out aString block
2. 数据类型String的常量池特性
2.1 synchronized代码块不要使用String作为锁对象
在JVM中具有String常量池缓存功能,如下代码返回为true。
public class StringTest {
public static void main(String[] args) {
String a = "a";
String b = "a";
//打印true
System.out.println(a == b);
}
}