1、复习synchronized
案例:
1、创建资源类,提供操作数据的方法
2、创建3个售票员线程,卖出30张票
class Ticket{
private int ticket=30;
public synchronized void saleTickets(){
if(ticket>0){
System.out.println(Thread.currentThread().getName()+"卖出:"+(ticket--)+"剩余:"+ticket);
}
}
}
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<40;i++) {
ticket.saleTickets();
}
}
},"售票员1").start();
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<40;i++) {
ticket.saleTickets();
}
}
},"售票员2").start();
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<40;i++) {
ticket.saleTickets();
}
}
},"售票员3").start();
}
}
2、使用Lock接口改写例子
注意:使用Lock需进行异常的处理
class LTicket{
private int ticket=30;
//创建可重入锁
private final ReentrantLock lock=new ReentrantLock();
public void lsaleTicket(){
lock.lock();
//避免在操作数据时出现异常导致锁无法释放
try {
if(ticket>0){
System.out.println(Thread.currentThread().getName()+"卖出:"+(ticket--)+"剩余:"+ticket);
}
}finally {
lock.unlock();
}
}
}
public class LSaleTickets {
public static void main(String[] args) {
LTicket ticket=new LTicket();
new Thread(()->{
for(int i=0;i<40;i++){
ticket.lsaleTicket();
}
//native:start方法执行,线程不一定立刻创建,取决与硬件资源的状态
},"售票员1").start();
new Thread(()->{
for(int i=0;i<40;i++){
ticket.lsaleTicket();
}
},"售票员2").start();
new Thread(()->{
for(int i=0;i<40;i++){
ticket.lsaleTicket();
}
},"售票员3").start();
}
}
3、synchronized与Lock的区别
- Lock 是一个接口,而 synchronized 是 Java 中的关键字,synchronized 是内置的语言实现;
2. synchronized 在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而 Lock 在发生异常时,如果没有主动通过 unLock()去释放锁,则很可能造成死锁现象,因此使用 Lock 时需要在 finally 块中释放锁;
3. Lock 可以让等待锁的线程响应中断,而 synchronized 却不行,使用synchronized 时,等待的线程会一直等待下去,不能够响应中断;