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();
                }
            }
        }
    }
  • 相关阅读:
    Thinking in Java 第十六章学习笔记----数组
    Thinking in Java第十五章学习笔记----泛型
    Thinking in Java第十四章学习笔记----类型信息
    Thinking in Java第十三章学习笔记----字符串
    Kaggle竞赛--Titanic:Machine Learning from Disaster
    sklearn 常用算法参数设置与选择
    Pandas 入门知识
    机器学习常用数据集
    感知机PLA
    决策树CART--原理与实现
  • 原文地址:https://www.cnblogs.com/yinmu/p/15219140.html
Copyright © 2011-2022 走看看