zoukankan      html  css  js  c++  java
  • JAVA 线程安全与同步机制

    一、模拟线程不安全场景。

    public class MyRunnable implements Runnable {
        private int a = 100; //共享的数据
    
        @Override
        public void run() {
            while (true) {
                if (a > 0) {
                    //多个MyRunnable线程同时访问共享数据,结果不是想要的。导致线程不安全
                    System.out.println(a);
                    a--;
                } else {
                    break;
                }
            }
        }
    }
    public static void main(String[] args) {
            MyRunnable myRunnable = new MyRunnable();
            new Thread(myRunnable).start();
            new Thread(myRunnable).start();
            new Thread(myRunnable).start();
        }

    二、使用对象监视器解决问题,使其安全。将线程类修改如下。

    public class MyRunnable implements Runnable {
        private int a = 100; //共享的数据
    
        Object obj = new Object();
    
        @Override
        public void run() {
            while (true) {
                //使用了一个锁对象。这种锁又叫:同步锁,对象锁,对象监视器。
                synchronized (obj) {
                    if (a > 0) {
                        System.out.println(a);
                        a--;
                    } else {
                        break;
                    }
                }
            }
        }
    }

    对象锁

      优点:保证了线程安全,同一时间只能有一个线程执行共享数据。

      缺点:程序频繁的判断锁、获取锁和释放锁,程序的效率会降低。

    三、使用同步方法解决问题,其实思想和上面解决方法一直。将线程类修改如下。

    public class MyRunnable implements Runnable {
        private int a = 100; //共享的数据
    
        Object obj = new Object();
    
        @Override
        public void run() {
            while (true) {
                boolean bo = inA();
                if (!bo) break;
            }
        }
    
        //使用的也是对象锁,锁对象就是this
        public synchronized boolean inA(){
            if (a > 0) {
                System.out.println(a);
                a--;
                return true;
            } else {
                return false;
            }
        }
    
    }

    三、使用静态同步方法解决问题,与同步方法的区别是锁对象不同。将线程类修改如下。

    public class MyRunnable implements Runnable {
        private static int a = 100; //共享的数据
    
        Object obj = new Object();
    
        @Override
        public void run() {
            while (true) {
                boolean bo = inA();
                if (!bo) break;
            }
        }
    
        //使用的也是对象锁,锁对象就是奔本类的class属性->class文件对象(反射机制)。MyRunnable.class
        public static synchronized boolean inA(){
            if (a > 0) {
                System.out.println(a);
                a--;
                return true;
            } else {
                return false;
            }
        }
    
    }

     使用Lock锁解决线程安全问题,将线程类修改如下。

    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class MyRunnable implements Runnable {
        private static int a = 100; //共享的数据
    
        /*
        1、创建ReentrantLock对象。
        2、在可能出现线程安全问题代码【前】调用【lock()】方法获取锁
        3、在可能出现线程安全问题代码【后】调用【unlock()】方法释放锁
         */
        Lock lock = new ReentrantLock();
    
        // @Override
        public void run() {
            while (true) {
                lock.lock();
                try {
                    if (a > 0) {
                        System.out.println(a);
                        a--;
                    } else {
                        break;
                    }
                } catch (Exception e) {
                } finally { //无论是否异常,都需要是否锁
                    lock.unlock();
                }
            }
        }
    }
  • 相关阅读:
    Maximum Depth of Binary Tree
    Single Number
    Merge Two Sorted Lists
    Remove Nth Node From End of List
    Remove Element
    Remove Duplicates from Sorted List
    Add Two Numbers
    编译视频直播点播平台EasyDSS数据排序使用Go 语言 slice 类型排序的实现介绍
    RTMP协议视频直播点播平台EasyDSS在Linux系统中以服务启动报错can’t evaluate field RootPath in type*struct排查
    【解决方案】5G时代RTMP推流服务器/互联网直播点播平台EasyDSS实现360°全景摄像机VR直播
  • 原文地址:https://www.cnblogs.com/yinmu/p/15219140.html
Copyright © 2011-2022 走看看