• [Java] Thread -- 避免Race Condition (Synchronized)


    public class TestRaceCondition implements Runnable{
    
        public static int counter = 0;
    
        public static void main(String[] args) {
    
            List<Thread> threads = new ArrayList<>();
            //產生threads,加入ArrayList
            for( int i=0 ; i < 10 ; i++) {
                TestRaceCondition runnable = new TestRaceCondition();
                Thread t1 = new Thread(runnable,"T"+i);
                threads.add(t1);
            }
            //一起發動所有的thread
            for (Thread thread : threads) {
                thread.start();
            }
            try {
                //main thread 等待所有執行緒結束
                for (Thread thread : threads) {
                    thread.join();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //印出最後的值
            System.out.println("finally counter = "+counter);
    
        }
    
        @Override
        public void run() {
            for ( int i= 0  ; i < 1000 ;i ++){
                incrementCounter();
            }
        }
    
        public static  void incrementCounter(){   
            counter = counter + 1;
        }
    
    }

    [原始程式架構]

    設立10個執行序塞入List中,再同時執行程序,各自生成一個Runnable的物件,執行run(),再incrementCounter()

    此處會有共搶的Race Condtion發生,避免此狀況,可使用synchronized管控程序

    (%所有synchronized標的都需唯一)

    1. static 方法 加上 synchronized

    所有用到這個方法的都是受到管控的,鎖頭為類別自身(TestRaceCondition.class)  

     public static synchronized void incrementCounter(){  
            counter = counter + 1;
        }

    2.方法中設立專鎖物件控管執行方法

        //設立專鎖物件
        public  final static Object locker = new Object(); 
        
        @Override
        public void run() {
            for ( int i= 0  ; i < 1000 ;i ++){
                synchronized (TestRaceCondition.locker)
                incrementCounter();
            }
        }

    3. 一般方法中加上 synchronized

    所有用到這個方法的都是受到管控的,鎖頭為自身物件()

    但此處每個Thread都各自生成物件執行程式,所以不具管控性,需調整程式為 => 生成一個執行物件,所有程序都使用同一物件

    public static void main(String[] args) {
    .
    .
            List<Thread> threads = new ArrayList<>();
            TestRaceCondition runnable = new TestRaceCondition();
            for( int i=0 ; i < 10 ; i++) {
                Thread t1 = new Thread(runnable,"T"+i);
                threads.add(t1);
    .
    .
    
        @Override
        public synchronized void run() {
            for ( int i= 0  ; i < 1000 ;i ++){
                incrementCounter();
            }
        }
  • 相关阅读:
    oracle的 listagg() WITHIN GROUP () 行转列函数的使用
    redis-配置文件详解
    Redis下载安装步骤及操作命令
    探索linux好玩的东西
    发送邮件的工具类
    微信小程序 云开发天然鉴权获取手机号
    JS 设计模式 -代理模式
    语言之魂——原型模式
    微信小程序 云开发中部分用户获取不到unionId
    js封装三级联动
  • 原文地址:https://www.cnblogs.com/pyleu1028/p/10341473.html
Copyright © 2020-2023  润新知