(二十一)线程同步机制——线程锁synchronized

(二十一)线程同步机制——线程锁synchronized


0 线程安全
例子:电影院买票,多人同时购买。一张票被同时购买,(多个线程访问共享数据(同一张电影票))产生了线程安全问题。

public class SaleTickets implements Runnable {
    private  static int  trickets=3;
    @Override
    public void run() {
        while (true){
                if (trickets>0){
                    System.out.println("在卖第"+trickets+" 张票");
                    trickets--;
                }
        }
    }
    public static void main(String[] args){
        //模拟卖票案例
        //只创建一个实现类,让多个线程都访问这个实现类
        SaleTickets s1 = new SaleTickets();
        Thread t1 = new Thread(s1);
        Thread t2 = new Thread(s1);
        t1.start();
        t2.start();
    }

运行结果:
在这里插入图片描述
1 为什么同一张票被买了2次,或者出现了0/-1张票?
         因为当第一个线程执行完打印操作,就失去了控制权,不能够进行其他操作(对票的加或者减),然后第二个线程得到了控制权,也真好打印了买票语句,因为第一个线程还没有来得急对票的数量进行操作,所以第二个线程也会打印一次这句话。同理,出现了0/-1票,就是当还有一张票的时候,线程都恰好运行到完了if控制语句,所以才会出现0/-1票数。         

2 线程同步
①同步代码块
Synchronized(锁对象){     可能出现线程安全的代码块    }
锁对象,就是一个对象,可以是任意的,但每个线程使用的锁对象必须要是同一个
作用:把代码块封锁,只让一个线程在代码快里面运行。
在这里插入图片描述
②同步方法
将共享的代码块抽取出来,封装成一个方法,在该方法的声明中添加synchronized关键词即可。然后在调用该方法。原理和同步代码块差不多,把方法里面的代码锁住,只不过同步锁对象是实现runnable接口的实现类本身。
在这里插入图片描述

③ Lock接口锁
lock接口. jdk1.5之后才出现.方便用户了解什么时候得到或者释放锁
lock()获取锁 ;unlock()释放锁;
用法: 1 创建一个lock的实现类reentrantion对象。2 在可能会出现线程安全的代码前调用lock()。3 当完成了,释放锁。
在这里插入图片描述 3 synchronized锁对象同步机制的原理
        锁对象即同步锁,也叫对象监视器。当一个线程执行的时候,遇到了synochronized同步代码块,线程会检查是否有锁对象,若有,则会获取锁对象,然后进入同步代码块中执行。当另一个线程执行到synochronized同步代码快的时候,也会检查是否有锁对象,因为锁对象被第一个线程获取了,他获取不到,所以该线程会进入阻塞状态,直到第一个线程执行完毕后,释放了锁对象。它才会继续执行,就像第一个线程一样。获取锁—执行同步代码—释放锁。
        也就是说,一个线程没有执行完毕,是不会让另一个线程去执行的。另一个线程想要执行,必须等到别的线程执行完毕释放锁才可以执行。
        优缺点:同步保证了线程的安全,却降低了线程的效率,因为需要不停的判断和释放。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值