Lock接口
Synchronized
Synchronized关键词回顾
synchronied是Java中的关键字,是一个同步锁.他修饰的对象有以下几种:
- 修饰一个代码块,被修饰的代码块成为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
- 修饰一个方法,被修饰的方法成为同步方法,起作用的范围是整个方法,作用的对象是调用这个方法的对象;
- 虽然可以使用synchronized来定义方法,但是synchronized并不属于方法定义的一部分,因此,synchronized关键字不能被继承.如果在父类中的某个方法是用了synchronized关键字,而在子类中覆盖了这个方法,在子类中的这个方法默认情况下并不是同步的,而必须现式地在子类的这个方法中加上synchronized关键字才可以.当然还可以在子类方法中调用父类中相应的方法,这样虽然子类中的方法不是同步的,当子类调用了父类的同步方法,因此,子类的方法也相当于是同步了
- 修饰一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
- 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象;
小例子:修饰一个方法
如果一个代码块被 synchronized 修饰了,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况:
class Ticket {
private int number = 30;
synchronized void sale() {
if (number > 0) {
System.out.println(Thread.currentThread().getName() + "=>sale:" + (number--) + ",剩余:" + number);
}
}
}
public class SaleTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 15; i++) {
ticket.sale();
}
}
}, "t1").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 15; i++) {
ticket.sale();
}
}
}, "t2").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 15; i++) {
ticket.sale();
}
}
}, "t3").start();
}
}
t1=>sale:30,剩余:29
t1=>sale:29,剩余:28
t1=>sale:28,剩余:27
t1=>sale:27,剩余:26
t1=>sale:26,剩余:25
t1=>sale:25,剩余:24
t1=>sale:24,剩余:23
t1=>sale:23,剩余:22
t1=>sale:22,剩余:21
t1=>sale:21,剩余:20
t1=>sale:20,剩余:19
t1=>sale:19,剩余:18
t1=>sale:18,剩余:17
t1=>sale:17,剩余:16
t1=>sale:16,剩余:15
t2=>sale:15,剩余:14
t2=>sale:14,剩余:13
t2=>sale:13,剩余:12
t2=>sale:12,剩余:11
t2=>sale:11,剩余:10
t2=>sale:10,剩余:9
t2=>sale:9,剩余:8
t2=>sale:8,剩余:7
t2=>sale:7,剩余:6
t2=>sale:6,剩余:5
t2=>sale:5,剩余:4
t2=>sale:4,剩余:3
t2=>sale:3,剩余:2
t2=>sale:2,剩余:1
t2=>sale:1,剩余:0
t1=>sale:30,剩余:29
t1=>sale:29,剩余:28
t1=>sale:28,剩余:27
t1=>sale:27,剩余:26
t1=>sale:26,剩余:25
t1=>sale:25,剩余:24
t1=>sale:24,剩余:23
t1=>sale:23,剩余:22
t1=>sale:22,剩余:21
t1=>sale:21,剩余:20
t1=>sale:20,剩余:19
t2=>sale:19,剩余:18
t2=>sale:18,剩余:17
t2=>sale:17,剩余:16
t2=>sale:16,剩余:15
t2=>sale:15,剩余:14
t2=>sale:14,剩余:13
t2=>sale:13,剩余:12
t2=>sale:12,剩余:11
t2=>sale:11,剩余:10
t2=>sale:10,剩余:9
t2=>sale:9,剩余:8
t2=>sale:8,剩余:7
t2=>sale:7,剩余:6
t2=>sale:6,剩余:5
t2=>sale:5,剩余:4
t1=>sale:4,剩余:3
t1=>sale:3,剩余:2
t1=>sale:2,剩余:1
t1=>sale:1,剩余:0
那么如果这个获取锁的线程由于要等待 IO 或者其他原因(比如调用 sleep 方法)被阻塞了,但是又没有释放锁,其他线程便只能干巴巴地等待,试想一 下,这多么影响程序执行效率。
因此就需要有一种机制可以不让等待的线程一直无期限地等待下去(比如只等 待一定的时间或者能够响应中断),通过 Lock 就可以办到。
(更新中)
|