- Lock and Condition interface给了程序员很高的自由度来控制锁, 但是通常不需要这么高的自由度
- Java提供一套更简便的机制来加锁 ---- synchronized 关键字 和 intrinsic lock
- Java 1.0之后, 每个object类都有一个 intrinsic lock, 每个object类都有wiat和notifyAll方法
synchronized
- 当一个方法使用synchronized修饰时, 锁会保护整个方法
- 也就是如果要执行这个方法, 线程必须拿到intrinsic object lock.
使用synchronized重写transfer方法:
class Bank
{
private double[] accounts;
public synchronized void transfer(int from, int to, int amount) throws InterruptedException {
while (accounts[from] < amount)
wait(); // wait on intrinsic object lock's single condition
accounts[from] -= amount;
accounts[to] += amount;
notifyAll(); // notify all threads waiting on the condition
}
public synchronized double getTotalBalance() { . . . }
}
The intrinsic locks and conditions have some limitations. Among them:
- You cannot interrupt a thread that is trying to acquire a lock.
- You cannot specify a timeout when trying to acquire a lock.
- Having a single condition per lock can be inefficient
- synchronized 关键字可以修饰静态方法, 也就是对 类 加锁, 也叫做类锁
public class Car {
public static synchronized void staticRuning1(Thread thread){
System.out.println(thread.getName()+ " static car1 得到锁");
System.out.println("------ static car1 is running ------");
working();
System.out.println(thread.getName()+ " static car1 释放锁");
System.out.println();
}
public static synchronized void staticRuning2(Thread thread){
System.out.println(thread.getName()+ " static car2 得到锁");
System.out.println("------ static car2 is running ------");
working();
System.out.println(thread.getName()+ " static car2 释放锁");
System.out.println();
}
public static void working(){
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
public class test02 {
public static void main(String[] args) {
//线程1 类
Thread t1 = new Thread(){
@Override
public void run() {
Car.staticRuning1(Thread.currentThread()); //同步类方法1
}
};
t1.start();
//线程2 类
Thread t2 = new Thread(){
@Override
public void run() {
Car.staticRuning2(Thread.currentThread()); //同步类方法2
}
};
t2.start();
}
}
Car类不能同时访问两个静态方法
- 另一种使用 intrinsic lock的方法是使用synchronized代码块
public void transfer(int from, int to, int amount)
{
synchronized (lock) // an ad-hoc lock
{
accounts[from] -= amount;
accounts[to] += amount;
}
System.out.println(. . .);
}
- 原子性: synchronized 关键字。锁操作,基于 monitorenter 和 monitorexit 字节码指令,保证同步块只有单一线程执行。
- 可见性: synchronized 等锁机制。同步块的可见性是由“对一个变量执行 unlock 操作之前,必须先把此变量同步回主内存中(执行 store、write 操作)”这条规则获得的。
- 有序性: synchronized 等锁机制,同步块的有序性是由“一个变量在同一个时刻只允许一条线程对其进行 lock 操作”这条规则获得的。