• 00102_线程安全和线程同步


    1、线程安全

      (1)如果有多个线程在同时运行,而这些线程可能会同时运行这段代码;

      (2)程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的;

      (3)代码演示:

        ①模拟票

     1 public class Ticket implements Runnable {
     2     // 共100票
     3     int ticket = 100;
     4 
     5     @Override
     6     public void run() {
     7         // 模拟卖票
     8         while (true) {
     9             if (ticket > 0) {
    10                 // 模拟选坐的操作
    11                 try {
    12                     Thread.sleep(1);
    13                 } catch (InterruptedException e) {
    14                     e.printStackTrace();
    15                 }
    16                 System.out.println(Thread.currentThread().getName() + "正在卖票:"
    17                         + ticket--);
    18             }
    19         }
    20     }
    21 }

        ②测试类

     1 public class ThreadDemo {
     2     public static void main(String[] args) {
     3         // 创建票对象
     4         Ticket ticket = new Ticket();
     5 
     6         // 创建3个窗口
     7         Thread t1 = new Thread(ticket, "窗口1");
     8         Thread t2 = new Thread(ticket, "窗口2");
     9         Thread t3 = new Thread(ticket, "窗口3");
    10 
    11         t1.start();
    12         t2.start();
    13         t3.start();
    14     }
    15 }

        ③运行结果:

      

      (4)上面程序出现了问题,错误的票0、-1;

      (5)其实,线程安全问题都是由全局变量及静态变量引起的;

      (6)若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;

      (7)若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

    2、线程同步(线程安全处理Synchronized)

      (1)线程同步的方式有两种:

        ①同步代码块;

        ②同步方法

      (2)同步代码块

        ①同步代码块: 在代码块声明上 加上synchronized

    synchronized (锁对象) {
        可能会产生线程安全问题的代码
    }

        ②同步代码块中的锁对象可以是任意的对象;但多个线程时,要使用同一个锁对象才能够保证线程安全。

        ③使用同步代码块,对卖票案例中Ticket类进行如下代码修改,当使用了同步代码块后,上述的线程的安全问题,解决了。

     1 public class Ticket implements Runnable {
     2     // 共100票
     3     int ticket = 100;
     4     // 定义锁对象
     5     Object lock = new Object();
     6 
     7     @Override
     8     public void run() {
     9         // 模拟卖票
    10         while (true) {
    11             // 同步代码块
    12             synchronized (lock) {
    13                 if (ticket > 0) {
    14                     // 模拟电影选坐的操作
    15                     try {
    16                         Thread.sleep(10);
    17                     } catch (InterruptedException e) {
    18                         e.printStackTrace();
    19                     }
    20                     System.out.println(Thread.currentThread().getName()
    21                             + "正在卖票:" + ticket--);
    22                 }
    23             }
    24         }
    25     }
    26 }

      (3)同步方法

        ①同步方法:在方法声明上加上synchronized;

    1 public synchronized void method(){
    2        可能会产生线程安全问题的代码
    3 }

        ②同步方法中的锁对象是 this。

        ③使用同步方法,对电影院卖票案例中Ticket类进行如下代码修改,

     1 public class Ticket implements Runnable {
     2     //共100票
     3     int ticket = 100;
     4     //定义锁对象
     5     Object lock = new Object();
     6     @Override
     7     public void run() {
     8         //模拟卖票
     9         while(true){
    10             //同步方法
    11             method();
    12         }
    13     }
    14 
    15 //同步方法,锁对象this
    16     public synchronized void method(){
    17         if (ticket > 0) {
    18             //模拟选坐的操作
    19             try {
    20                 Thread.sleep(10);
    21             } catch (InterruptedException e) {
    22                 e.printStackTrace();
    23             }
    24             System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticket--);
    25         }
    26     }
    27 }

      (4)静态同步方法

        ①静态同步方法: 在方法声明上加上static synchronized;

        ②静态同步方法中的锁对象是 类名.class。

    public static synchronized void method(){
    可能会产生线程安全问题的代码
    }

    其实,线程安全问题都是由全局变量及静态变量引起的

  • 相关阅读:
    Linux——强制退出命令
    2019-08-07-安装jdk1.8配置环境变量
    2019-08-07-查看当前的系统版本-中文乱码显示
    2019-08-07-centos系统上文件出现乱码
    2019-08-06-centos6.4关闭防火墙-设置通过防火墙的端口
    2019-08-06-写批处理
    2019-08-06-centos 打包
    2019-07-26_解密黑客攻击前的准备
    2019-07-24-DOS 常用命令大全
    2019-07-24-windows一些常用命令-netsh
  • 原文地址:https://www.cnblogs.com/gzdlh/p/8099387.html
Copyright © 2020-2023  润新知