zoukankan      html  css  js  c++  java
  • 线程同步机制。

    ---恢复内容开始---

    线程安全问题:

    概述:场景:电影院有一百张票,现在用一个窗口卖1-100号票,属于单线程问题,无线程安全问题

          现在有两个窗口,分别卖1-50 和51-100号票,属于多线程问题,因为没有访问共享数    

          据,也不会有线程安全问题。但如果两个窗口卖的都是1-100号票,有共享数据,就会

          有安全问题。

    代码实现:

    public class Sell implements Runnable {
        private int ticket=100;
        @Override
        public void run() {
           while (true){
               if (ticket>0){
                   try {
                       Thread.sleep(10);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   System.out.println("正在卖第"+ticket+"张票");
                   ticket--;
               }
           }
        }
    }
     public static void main(String[] args) {
            Sell sell=new Sell();
            Thread t1=new Thread(sell);
            Thread t2=new Thread(sell);
            Thread t3=new Thread(sell);
            t1.start();
            t2.start();
            t3.start();
            //问题:
            //正在卖第100张票 
            // 正在卖第100张票
            //正在卖第97张票
            //正在卖第0张票
            //正在卖第-1张票
        }

    出现问题的原因:重复票:多个线程同时执行。 错误票:大家都进入if语句后,一个线程先执行,已经--,另一个线程后执行,就会产生错误数据。 

    解决线程安全问题:

    第一种方法:同步代码块。

    格式: synchronized (锁对象) { 可能会出现线程安全问题的代码 }

    注意:1、锁对象可以使用任意对象,但必须保证多个线程使用同一个锁对象。

       2、锁对象作用:把同步代码块锁住,只让一个线程在同步代码块中执行。

    public class Sell implements Runnable {
        private int ticket=100;
        Object obj=new Object();
        @Override
        public void run() {
           while (true){
               synchronized (obj){
                   if (ticket>0){
                       try {
                           Thread.sleep(10);
                       } catch (InterruptedException e) {
                           e.printStackTrace();
                       }
                       System.out.println("正在卖第"+ticket+"张票");
                       ticket--;
                   }
               }
           }
        }
    }

     同步技术原理:

    使用了一个锁对象,这个锁对象叫同步锁。

    三个线程一起争夺cpu的执行权,谁抢到了就执行run()。

      t1抢到cpu执行权,执行run(),遇到synchronized时,检查是否有锁对象,发现有

    ,就会获取锁对象,继续执行代码。

      t2抢到了cpu执行权,执行run(),遇到synchronized时,发现没有锁对象,会等到

      t1归还锁对象后,获取锁对象,才能继续执行。

    第二种方法:同步方法。

    使用步骤:

      1、把访问共享数据的代码提取出来,放到一个方法中。

      2、在方法上加synchronized修饰符。

    使用格式: 修饰符 synchronized 返回值类型  方法名 (){可能出问题的代码}

    锁对象:this。

    public class Sell implements Runnable {
    private int ticket=100;
    Object obj=new Object();
    @Override
    public void run() {
    while (true){
    sell();
    }
    }
    public synchronized void sell(){
    if (ticket>0){
    try {
    Thread.sleep(10);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println("正在卖第"+ticket+"张票");
    ticket--;
    }
    }
    }

    第三种方法:静态方法。

    上面的方法加上  static。

    锁对象:this是创建对象后产生的,静态方法优先于对象,静态方法的锁对象是本类的class属性。

    第四种方法: Lock 锁。

    java.util.concurrent.Locks.Lock 接口。

    Lock 提供了比synchronized更广泛的操作。

    Lock中的方法:void Lock()获取锁。 void unLock() 释放锁。

    实现类: java.util.concurrent.Locks.ReentrantLock  implements Lock.

    使用步骤:

      1、在成员位置创建一个ReentrantLock对象

      2、可能会出现安全问题的代码前调用Lock接口中的 Lock方法获取锁。

      3、......后调用  unLock方法   释放锁。

    public class Sell implements Runnable {
        private int ticket=100;
        Lock lock=new ReentrantLock();
        @Override
        public void run() {
           while (true){
               lock.lock();
               if (ticket>0) {
                   try {
                       Thread.sleep(10);
                       System.out.println("正在卖第" + ticket + "张票");
                       ticket--;
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }finally {
                       lock.unlock();
                   }
               }
           }
        }
    
    }
  • 相关阅读:
    本地及远程二级缓存
    ubuntu下使用golang、qml与ubuntu sdk开发桌面应用
    TCP之心跳包实现思路
    Java读书笔记1
    回文字符串
    6.1 遍历字符串
    linux系统文件夹的作用 good
    在线程中建立Form遇到的问题
    QTabWidget and QTabBar.的文字的颜色设置,三种方法
    Ring3下Hook NtQueryDirectoryFile隐藏文件
  • 原文地址:https://www.cnblogs.com/zhangyuhao/p/10799585.html
Copyright © 2011-2022 走看看