Single Thread Execution设计模式:同一时刻只允许一个线程访问共享资源。
synchronized关键字虽然可以保证single Thread Execution,但是使用不当可能会导致死锁。
死锁场景示例:吃面问题,A手持刀等待B放下叉,B手持叉等待A放下刀。
public class Tableware {
//餐具名称
private final String toolName;
public Tableware(String toolName){
this.toolName = toolName;
}
@Override
public String toString() {
return "Tool" + toolName;
}
}
public class EatNoodleThread extends Thread{
private String name;
private final Tableware leftTool;
private final Tableware rightTool;
public EatNoodleThread(String name,Tableware leftTool,Tableware rightTool){
this.name = name;
this.leftTool = leftTool;
this.rightTool = rightTool;
}
@Override
public void run() {
while(true){
this.eat();
}
}
private void eat(){
synchronized (leftTool){
System.out.println(name + " take up " + leftTool + "(left)");
synchronized (rightTool){
System.out.println(name + " take up " + rightTool + "(right)");
System.out.println(name + " is eating now");
System.out.println(name + " put down " + rightTool + "(right)");
}
System.out.println(name + " put down " + leftTool + "(left)");
}
}
public static void main(String args[]){
Tableware fork = new Tableware("fork");
Tableware knife = new Tableware("knife");
new EatNoodleThread("A",fork,knife).start();
new EatNoodleThread("B",knife,fork).start();
}
}
运行结果:双方僵持,都在等待对方放下
......
这种就是典型的交叉锁导致两个线程相互等待对方放下锁而发生死锁的情况,解决这种情况,需要将刀叉进行封装:
public class TablewarePair {
private final Tableware leftTool;
private final Tableware rightTool;
public TablewarePair(Tableware leftTool,Tableware rightTool){
this.leftTool = leftTool;
this.rightTool = rightTool;
}
public Tableware getLeftTool() {
return leftTool;
}
public Tableware getRightTool() {
return rightTool;
}
}
public class EatNoodleThread extends Thread{
private String name;
private TablewarePair tablewarePair;
public EatNoodleThread(String name,TablewarePair tablewarePair){
this.name = name;
this.tablewarePair = tablewarePair;
}
@Override
public void run() {
while(true){
this.eat();
}
}
private void eat(){
synchronized (tablewarePair){
System.out.println(name + " take up " + tablewarePair.getLeftTool() + "(left)");
System.out.println(name + " take up " + tablewarePair.getRightTool() + "(right)");
System.out.println(name + " is eating now");
System.out.println(name + " put down " + tablewarePair.getRightTool() + "(right)");
System.out.println(name + " put down " + tablewarePair.getLeftTool() + "(left)");
}
}
public static void main(String args[]){
Tableware fork = new Tableware("fork");
Tableware knife = new Tableware("knife");
TablewarePair tablewarePair = new TablewarePair(fork,knife);
new EatNoodleThread("A",tablewarePair).start();
new EatNoodleThread("B",tablewarePair).start();
}
}
测试结果正常:
......
......
将某个类设计成线程安全的类,用Single Thread Execution控制是其中的方法之一。若是子类继承线程安全的类并且打破了 Single Thread Execution,就会破坏方法的安全性,这种情况一般称为异常继承。