线程安全问题解决的三个方案

1.解决线程安全问题有三种方案:
  1.1  同步代码块
        syncnized(锁对象){
            可能出现线程安全问题的代码,访问了共享数据的daima
        }
        
        注意:a.代码块中的锁对象,可以使用任意对象
              b.必须保证多线程使用的锁对象是同一个
              c.锁对象将同步代码块锁住,只让一个线程在同步代码块中执行
              同步中的线程,没有执行完毕不会释放锁,,同步外的线程没有锁对象,进不去同步
              thread.sleep() 进入休眠后会释放CPU的执行权,但不会释放锁对象,只有出了同步代码块才会释放锁对象
              
  2. 同步方法
        同步方法也会把方法内部的代码锁住,只让一个线程执行,锁对象就是实现类对象(new Runable(),也就是this)
        静态的同步方法,锁对象不能是this,this是创建对象之后产生的,静态优先于对象,静态方法的锁对象是本类的class属性-->class文件对象
 
 3. 锁机制
        lock实现提供了比使用synchronized方法和语句更加广泛的锁定操作
        lock l = new reentrantlock() 
        l.lock 在可能出现线程安全问题代码前,加上
        l.unlock   在可能出现线程安全问题代码后,加上 这个更加建议放在finally中,无论怎样都释放锁,提高性能

 

package threaddemo;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**创建线程执行的任务
 * 这里以售卖三个窗口共同售卖100张火车票为例
 * 三个窗口要共同售卖100张火车票,相当于三条线程访问共同的资源,存在数据安全问题。今天提出三个解决方案。
 * @author Jeady
 * @Date 2019/8/2
 */
public class lockTacket implements Runnable{
   static   int tacket = 100; //因为同步代码块中用到了静态同步,因此这里为了不影响效果,加上static
    Object obj = new Object();
    Lock lock = new ReentrantLock();
    public void run() {

        while (true){

            //解决方案一:同步代码块
            synchronized (obj){
                if (tacket>0) {
                    try {
                        //线程休眠,释放CPU执行权,但并不一定释放锁对象,只有出了同步代码块才释放锁对象
                        Thread.sleep(10);
                        System.out.println(Thread.currentThread().getName() + "正在销售第" + tacket + "张票");
                        tacket--;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }

                //demo1();

          //  demo2();

        }
    }

    //解决方案二:同步方法
    private static synchronized void demo1() {
            if (tacket>0){
                try {
                    //线程休眠,释放CPU执行权,但并不一定释放锁对象,只有出了同步代码块才释放锁对象
                    Thread.sleep(10);
                    System.out.println(Thread.currentThread().getName()+"正在销售第"+tacket+"张票");
                    tacket--;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

        }
    }

    //解决方案三:锁机制
    private void demo2() {
        lock.lock(); //用在可能出现线程安全的代码之前
        if (tacket>0){
            try {
                Thread.sleep(10);
                System.out.println(Thread.currentThread().getName()+"正在销售第"+tacket+"张票");
                tacket--;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();//用在可能出现线程安全问题代码之后
            }

        }


    }
}
package threaddemo;

/**定义三个线程
 * @author Jeady
 * @Date 2019/8/2
 */
public class ThreadRun01 {

    public static void main(String[] args) {
        lockTacket lockTacket = new lockTacket();
        //创建三个线程
        Thread t1 = new Thread(lockTacket);
        Thread t2 = new Thread(lockTacket);
        Thread t3 = new Thread(lockTacket);
        //开启三条线程
        t1.start();
        t2.start();
        t3.start();

    }
}

效果如下:

线程安全问题解决的三个方案_第1张图片

你可能感兴趣的:(线程安全问题解决的三个方案)