zoukankan      html  css  js  c++  java
  • 线程安全,syncronized 用法

    1,为什么有线程安全问题?

    当多个线程同时共享同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题。

    public class TrainThread implements Runnable {
    
        // 定义初始化票100张
        private int ticketCount = 100;
    
        public void run() {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            while (ticketCount > 0) {
                System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
                ticketCount--;
            }
        }
    
    }
    public class App {
        public static void main(String[] args) throws InterruptedException {
            TrainThread trainThread = new TrainThread();
            
            //模拟了两个线程,必须都用同一个Runnable 的子类对象,才能叫 实现资源的共享
            Thread thread1 = new Thread(trainThread);
            Thread thread2 = new Thread(trainThread);
            thread1.start();
            thread2.start();
        }
    
    }

    可能出现的情况:同时卖了某一张票

    Thread-1卖出了第1张票
    Thread-1卖出了第2张票
    Thread-0卖出了第1张票
    Thread-0卖出了第4张票
    Thread-1卖出了第3张票
    Thread-1卖出了第6张票

    :为什么使用线程同步或使用锁能解决线程安全问题呢?

    :将可能会发生数据冲突问题(线程不安全问题),只能让当前一个线程进行执行。代码执行完成后释放锁,让后才能让其他线程进行执行。这样的话就可以解决线程不安全问题。

    :什么是多线程之间同步?

    :当多个线程共享同一个资源,不会受到其他线程的干扰

    2, 实现线程同步,syncronized 的用法

    解决一:

    锁对象

    syncronized 同步代码块:就是将可能会发生线程安全问题的代码,给包括起来。

    synchronized(同一个数据){

     可能会发生线程冲突问题

    }

    public class TrainThread implements Runnable {
    
        // 定义初始化票100张
        private int ticketCount = 100;
        //定义了一个共享的对象
        private Object obj = new Object();
    
        public void run() {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (obj) {
                while (ticketCount > 0) {
                    System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
                    ticketCount--;
                }
            }
    
        }
    
    }

    解决二:

    同步函数,

    在方法上修饰synchronized 称为同步函数

    锁方法

    public class TrainThread implements Runnable {
    
        // 定义初始化票100张
        private int ticketCount = 100;
    
        public void run() {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            sale();
        }
    
        private synchronized void sale() {
            while (ticketCount > 0) {
                System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
                ticketCount--;
            }
        }
    }

    3,同步函数,所方法,其实是this 锁

    证明,两个线程,一个线程走同步代码块,(锁住了自定义object对象)的代码,

    另一个走同步函数,锁方法的的代码,结果数据有冲突,证明了syncronized 没有效,并没有锁住同一资源

    将锁对象的object 换成this,则没有数据冲突

    4,是静态同步函数?

    方法上加上static关键字,使用synchronized 关键字修饰 或者使用类.class文件。

    静态的同步函数使用的锁是  该函数所属字节码文件对象

    还是加syncronized,和之前没有区别,锁方法

    public class TrainThread implements Runnable {
    
        // 定义初始化票100张
        private static int ticketCount = 100;
    
        public void run() {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            sale();
        }
    
        private  synchronized static void sale() {
            while (ticketCount > 0) {
                System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
                ticketCount--;
            }
        }
    }

    锁当前类的的字节码文件的对象,不是this,或者自定义的对象

    public class TrainThread implements Runnable {
    
        // 定义初始化票100张
        private static int ticketCount = 100;
    
        public void run() {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (TrainThread.class) {
                while (ticketCount > 0) {
                    System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
                    ticketCount--;
                }
            }
        }
    
    }
  • 相关阅读:
    $.each与$().each
    冒泡排序和用for循环画菱形
    windows10, 安装wamp无法启动服务的问题
    使用MySql数据库, 浏览器接收返回数据报错SyntaxError: unterminated string literal
    SWT, JFace必须的jar包和有可能会用到的jar
    easyui中tree使用simpleData的形式加载数据
    树形菜单的json字符串的拼接
    选择合适的String拼接方法(这篇博客是我抄的)
    hibernate进行多表联合查询
    操作文件和目录
  • 原文地址:https://www.cnblogs.com/pickKnow/p/11017001.html
Copyright © 2011-2022 走看看