如何解决多线程并发访问一个资源的安全性问题?
原子操作:所謂原子操作是指不會被線程調度機制打斷的操作;這種操作一旦開始,就一直運行到結束,中間不會有任何 context switch (切[1] 換到另一個線程)。
關于我對原子操作的理解:原子操作就類似于化學中的原子為不可分割的單位,也就是如果把需要操作的代碼塊能夠順序執行中間不為被干擾。
這樣就不會出現線程不安全情況(案例中的購票系統出現負數的情況),這種原子操作思想還是挺有用的,在這提提自己也不了解=-=。
解決方案:保證打印編號和操作必須同步執行:System.out.println(Thread.currentThread().getName()+”—賣出的票”+tickets–);
也就是上述代碼中ticket–與輸出同步執行,不能因為某個線程輸出后就休眠而不執行減減操作。
方式一、同步代碼塊:
語法:
案例:
package com.test;//線程安全 public class Main { public static void main(String[] args){ SaleThread saleThread=new SaleThread(); new Thread(saleThread,"線程一").start(); new Thread(saleThread,"線程二").start(); new Thread(saleThread,"線程三").start(); new Thread(saleThread,"線程四").start(); } } class SaleThread implements Runnable{ private int tickets=10; public void run(){ //synchronized (this) {while(tickets>0){ try{ Thread.sleep(10); }catch(InterruptedException e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"---賣出的票"+tickets--); // } } } }*輸出結果:
線程二—賣出的票10
線程一—賣出的票9
線程四—賣出的票8
線程三—賣出的票7
線程二—賣出的票5
線程一—賣出的票6
線程三—賣出的票4
線程四—賣出的票3
線程一—賣出的票1
線程二—賣出的票2
線程三—賣出的票-1
線程四—賣出的票0*
分析:上述結果中出現負數和0情況(如果數據量大還會出現重復情況)。
方式二、同步方法
使用synchronized修飾的方法就叫同步方法,表示a線程在執行該方法的時候其他線程只能等待。
代碼:
方式三、同步鎖-鎖機制lock
為了保證每個線程都能正常執行原子操作,java引入了線程同步機制。
同步監聽對象/同步鎖/同步監聽器/互斥鎖(a進去b被排斥,保證只有一個進程執行)
對象的同步鎖只是一個概念,可以想象為在對象上標記一個鎖。
java程序運行使用任何對象作為同步監聽對象,但是一般的,我們試驗當前并發訪問的共同資源作為同步監聽對象。
注意:在任何時候,最多允許一個線程擁有同步鎖,誰拿到鎖就進入代碼塊,其他線程只能等待。
總結
以上是生活随笔為你收集整理的如何解决多线程并发访问一个资源的安全性问题?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图像格式jpg、jpeg、jpe、gif
- 下一篇: 磁盘“簇”