package com.company.thread.synchronize;
/**
* @Description TODO
* @Author zhouxinjian
* @Date 2019-07-19 09:49
**/
public class PublicVar {
public String username = "A";
public String password = "AA";
public synchronized void setValue(String username, String password) {
try {
this.username = username;
Thread.sleep(5000);
this.password = password;
System.out.println("setValue method thread name ="+Thread.currentThread().getName()+" username="+username+" password="+password);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void getValue() {
System.out.println("getValue method thread name ="+Thread.currentThread().getName()+" username="+username+" password="+password);
}
public static void main(String[] args) throws InterruptedException {
PublicVar var = new PublicVar();
Thread thread = new Thread(){
@Override
public void run() {
var.setValue("B", "BB");
}
};
thread.start();
Thread.sleep(200);
var.getValue();
}
}
当A线程调用anyObject对象加入synchronized 关键字的X方法时,A线程就获得X方法锁,也即对象锁,所以其他线程必须等A线程执行完毕才可以调用X方法,但B线程可以调用其他非synchronized同步方法。
当A线程调用anyObject对象加入synchronized 关键字的X方法时,A线程就获得X方法锁,也即对象锁,所以其他线程必须等A线程执行完毕才可以调用X方法,如果B线程如果调用声明了synchronized的非X方法时,必须等A线程将X方法执行完,也就是释放了对象锁后才可以学调用。
2、synchronized 锁重入
在使用synchronized时,当一个线程得到一个对象锁后,再次请求对象锁时是可以得到该对象的锁的。即在synchronized方法/块的内部调用本类的其他synchronized方法/块时,是永远得到锁的。
"可重入锁“的概念是:自己可以再次获得自己的内部锁。如有一个线程获得某个对象的锁,此时这个对象锁还没释放,当其再次想获取这个对象锁的时候还是可以获取的,如果不可锁重入,就会造成死锁。
当存在子父类继承关系时,子类完全可以通过“可重入锁”调用父类同步方法。
多个线程调用同一个对象的不同名称的synchronized同步方法或synchronized(this)同步代码块时,调用的效果是按顺序执行,同步阻塞的。
这说明synchronized方法或synchronized(this)同步代码块分别有两种作用:
synchronized同步
(1)对其他synchronized 同步方法或synchronized(this)同步代码块调用呈阻塞作用
(2)同一时间只有一个线程可以执行synchronized同步方法中的代码。
(3) synchronized(非this对象)同步,对象监视器必须是同一个,否则就是异步调用。
/**
* @Description TODO
* @Author zhouxinjian
* @Date 2019-07-19 10:15
**/
public class Service {
public synchronized void service1() {
System.out.println("service1");
service2();
}
public synchronized void service2() {
System.out.println("service2");
service3();
}
public synchronized void service3() {
System.out.println("service3");
}
public static void main(String[] args) {
Service service = new Service();
Runnable runnable = () -> {
service.service1();
};
new Thread(runnable).start();
}
}
synchronized还可以用在static静态方法上,如果这样就是对当前的*.java 对应的class类进行持锁。Class锁可以对类的所有对象实例起作用。
public class Service1 {
public synchronized static void printA() {
try {
System.out.println("线程 "+Thread.currentThread().getName()+" "+System.currentTimeMillis()+"进入printA");
Thread.sleep(3000);
System.out.println("线程 "+Thread.currentThread().getName()+" "+System.currentTimeMillis()+"离开printA");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized static void printB() {
try {
System.out.println("线程 "+Thread.currentThread().getName()+" "+System.currentTimeMillis()+"进入printB");
Thread.sleep(3000);
System.out.println("线程 "+Thread.currentThread().getName()+" "+System.currentTimeMillis()+"离开printB");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Service1 s1 = new Service1();
Service1 s2 = new Service1();
new Thread(()->{
s1.printA();
},"A").start();
new Thread(()->{
s2.printB();
},"B").start();
}
}