8.2.解决线程安全问题的三种方法

方法1:同步代码块

synchronized ( 对象){
// 需要被同步的代码;
}

class Window extends Thread{
//    private int ticket=100;//这样会有300张票
   private static int ticket=100;//只有100张票
//    Object obj=new Object();//不能用obj,会出现3个obj
    static Object obj=new Object();//用静态的

    @Override
    public void run() {
        while(true){
            synchronized (obj){//这个地方如果用this,代表t1,t2,t3
                //可以用Window.class  类也是对象  只会加载一次
                //Class clazz=Window.class
                if(ticket>0){
                    System.out.println(Thread.currentThread().getName()+":卖票,票号为"+ticket);
                    ticket--;
                }else{
                    break;
                }
            }
        }
    }
}

方法2:同步方法:

public synchronized void show (String name){
需要被同步代码
}

class Window2 implements Runnable{
    private  int ticket=100;
    @Override
    public void run() {
        while (true){
            show();
        }

    }
    //同步方法
    private synchronized void show(){//同步监视器:this
            if(ticket>0){
                System.out.println(Thread.currentThread().getName()+"卖票,票号为:"+ticket);
                ticket--;
            }
    }
}

方法3:Lock( 锁)(jdk5.0出现)

class A{
private final ReentrantLock lock = new ReenTrantLock();
public void m(){
lock.lock();
try{
// 保证线程安全的代码;
}
finally{
lock.unlock();
}
}
}

class Window implements Runnable{
private int tecket=100;
private final ReentrantLock lock=new ReentrantLock();
    @Override
    public void run() {
        while(true){
            try{
                lock.lock();
                if(tecket>0)
                {
                    try {//卖票慢点
                        sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+":售票,票号为:"+tecket);
                    tecket--;
                }else{
                    break;
                }

            }finally{
                lock.unlock();
            }
        }

    }
}

synchronized 与 Lock 的对比:

1. Lock是显式锁(手动开启和关闭锁,别忘记关闭锁),synchronized是隐式锁,出了作用域自动释放
2. Lock只有代码块锁,synchronized有代码块锁和方法锁
3. 使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性(提供更多的子类)

优先使用顺序:
Lock >同步代码块(已经进入了方法体,分配了相应资源)>同步方法(在方法体之外)
posted @ 2021-04-16 15:41  袁中  阅读(152)  评论(0编辑  收藏  举报