如何實(shí)現(xiàn)Java線程安全問題
這篇文章主要介紹了如何實(shí)現(xiàn)Java線程安全問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
解決線程安全問題的第一種方案:使用同步代碼塊
格式:
synchronized(鎖對(duì)象) {
可能會(huì)出現(xiàn)線程安全問題的代碼(訪問了共享數(shù)據(jù)的代碼)
}
注意:代碼塊中的鎖對(duì)象,可以是任意對(duì)象,但必須保證多個(gè)線程之間使用的是同一個(gè)
鎖對(duì)象的作用是把同步代碼塊鎖住,同一時(shí)間只能讓一個(gè)線程在同步代碼塊中執(zhí)行
package com.fgy.demo02; /** * 實(shí)現(xiàn)賣票案例 */ public class RunnableImpl implements Runnable { private int ticket = 100; Object obj = new Object(); @Override public void run() { while (true) { synchronized (obj) { if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在買第" + ticket + "張票"); ticket--; } } } } }
package com.fgy.demo02; public class Demo01Ticket { public static void main(String[] args) { RunnableImpl run = new RunnableImpl(); new Thread(run).start(); new Thread(run).start(); new Thread(run).start(); } }
解決線程安全問題的第二種方案:使用同步方法
使用步驟:
1.把訪問了共享數(shù)據(jù)的代碼抽取出來,放到一個(gè)方法中
2.在方法上添加synchronized修飾符
格式:
修飾符 synchronized 返回值類型 方法名(...) {
可能會(huì)出現(xiàn)線程安全問題的代碼(訪問了共享數(shù)據(jù)的代碼)
}
同步方法的鎖對(duì)象是:this
靜態(tài)同步方法的鎖對(duì)象不能是this,因?yàn)閠his是創(chuàng)建對(duì)象后產(chǎn)生的,靜態(tài)方法優(yōu)先于對(duì)象
靜態(tài)方法的鎖對(duì)象是本類的class文件對(duì)象
package com.fgy.demo03; /** * 實(shí)現(xiàn)賣票案例 */ public class RunnableImpl implements Runnable { private int ticket = 100; @Override public void run() { while (true) { payTicket(); } } public synchronized void payTicket() { if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在買第" + ticket + "張票"); ticket--; } } }
解決線程安全問題的第三種方案:使用lock鎖
使用步驟:
1.在成員位置創(chuàng)建ReenterantLock對(duì)象
2.在可能出現(xiàn)安全問題的代碼前調(diào)用Lock接口中的方法lock()獲取鎖
3.在可能出現(xiàn)安全問題的代碼后調(diào)用Lock接口中的方法unlock()釋放鎖
package com.fgy.demo04; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 實(shí)現(xiàn)賣票案例 */ public class RunnableImpl implements Runnable { private int ticket = 100; Lock l = new ReentrantLock(); /*@Override public void run() { while (true) { l.lock(); if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在買第" + ticket + "張票"); ticket--; } l.unlock(); } }*/ @Override public void run() { while (true) { l.lock(); if (ticket > 0) { try { Thread.sleep(100); System.out.println(Thread.currentThread().getName() + "正在買第" + ticket + "張票"); ticket--; } catch (InterruptedException e) { e.printStackTrace(); } finally { // 無論程序是否發(fā)生異常都會(huì)釋放鎖 l.unlock(); } } } } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解Mybatis-plus(MP)中CRUD操作保姆級(jí)筆記
本文主要介紹了Mybatis-plus(MP)中CRUD操作保姆級(jí)筆記,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11面向?qū)ο蠛兔嫦蜻^程的區(qū)別(動(dòng)力節(jié)點(diǎn)java學(xué)院整理)
很多朋友不清楚面向?qū)ο蠛兔嫦蜻^程有什么區(qū)別,接下來小編給大家整理了關(guān)于面向?qū)ο蠛兔嫦蜻^程的區(qū)別講解,感興趣的朋友可以參考下2017-04-04Spring Cloud升級(jí)最新Finchley版本的所有坑
這篇文章主要介紹了Spring Cloud升級(jí)最新Finchley版本的所有坑,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08SpringBoot整合定時(shí)任務(wù)之實(shí)現(xiàn)Scheduled注解的過程(一個(gè)注解全解決)
這篇文章主要介紹了SpringBoot整合定時(shí)任務(wù)之實(shí)現(xiàn)Scheduled注解的過程(一個(gè)注解全解決),本文通過使用場(chǎng)景分析給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09