synchronized关键字
脏读问题
package ch02.test1;
/*
脏读
*/
public class PublicVar {
private String name = "a";
private String pwd = "aa";
public void setValue(String name, String pwd) {
try {
this.name = name;
Thread.sleep(5000);
this.pwd = pwd;
System.out.println("setValue method thread name = " + Thread.currentThread().getName()
+ "name=" + this.name + " pwd=" + this.pwd);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void getValue() {
System.out.println("getValue method thread name=" + Thread.currentThread().getName()
+"name=" + this.name + " pwd=" + this.pwd);
}
}
class MyThread extends Thread {
private PublicVar publicVar;
public MyThread(PublicVar publicVar) {
this.publicVar = publicVar;
}
@Override
public void run() {
super.run();
this.publicVar.setValue("b","bb");
}
}
class Test {
public static void main(String[] args) {
try {
PublicVar publicVar = new PublicVar();
MyThread myThread = new MyThread(publicVar);
myThread.start();
Thread.sleep(200);
publicVar.getValue();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
output:
getValue method thread name=mainname=b pwd=aa
setValue method thread name = Thread-0name=b pwd=bb
-
脏读的原因
getValue()方法不同步 -
脏读的解决
用synchronized关键字修饰getValue()方法 -
当线程A调用anyObject对象的synchronized方法X时,A线程就获得了对象锁。此时:
- 其他线程必须等待A线程执行完X方法才能执行X方法,以及anyObject对象的其他synchronized方法
- 其他线程调用anyObject对象的非synchronized方法不受影响
synchronized锁重入
- 什么是锁重入
使用synchronized时,当一个线程得到一个对象锁后,它再次请求对象锁是可以获得对象锁的。
简而言之,就是自己可以再次获得自己的内部锁 - 如果没有锁重入,会导致死锁
package ch02.test2;
/*
可重入锁
*/
public class Service {
public synchronized void service1() {
service2();
System.out.println("service1");
}
public synchronized void service2() {
service3();
System.out.println("service2");
}
public synchronized void service3() {
System.out.println("service3");
}
}
class MyThread extends Thread {
@Override
public void run() {
super.run();
new Service().service1();
}
}
class Test {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
}
}
output:
service3
service2
service1
一些结论
- 当存在继承关系时,子类可以通过“可重入锁”调用父类的同步方法。
- 出现异常,锁自动释放
- 同步不可以继承