日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

静态变量的多线程同步问题

發(fā)布時(shí)間:2023/12/19 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 静态变量的多线程同步问题 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

我們先來討論一個(gè)問題,一個(gè)類的靜態(tài)變量當(dāng)類被多次實(shí)例化的時(shí)候,靜態(tài)變量是否會(huì)受影響?首先我們應(yīng)該清楚的是靜態(tài)變量是在類被JVM classloader的時(shí)候分配內(nèi)存,并且是分配在永久區(qū)而非堆內(nèi)存中。

當(dāng)我們用對(duì)象鎖來同步靜態(tài)變量的時(shí)候,我們來看一個(gè)例子。

public interface OrderService {public String getOrderNo(); }

先定義一個(gè)接口,獲取一個(gè)訂單編號(hào)。

public class OrderLockServiceImpl implements OrderService {static int num = 0; @Override synchronized public String getOrderNo() {SimpleDateFormat date = new SimpleDateFormat("YYYYMMDDHHMMSS"); return date.format(new Date()) + num++; } }

實(shí)現(xiàn)這個(gè)接口,并且用對(duì)象方法來操作靜態(tài)變量。

public class OrderTask implements Runnable {private CountDownLatch latch; private OrderService orderService; public OrderTask(CountDownLatch latch,OrderService orderService) {this.latch = latch; this.orderService = orderService; }@Override public void run() {try {latch.await(); } catch (InterruptedException e) {e.printStackTrace(); }System.out.printf("線程名%s訂單號(hào):%s\n",Thread.currentThread().getName(), orderService.getOrderNo()); } }

創(chuàng)建一個(gè)線程類,使用CountDownLatch來讓每一個(gè)線程都有出現(xiàn)的機(jī)會(huì),而不是某一個(gè)線程獨(dú)占。

public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final CountDownLatch latch = new CountDownLatch(1); for (int i = 0;i < 10;i++) {OrderService orderService = new OrderLockServiceImpl(); service.submit(new OrderTask(latch,orderService)); }latch.countDown(); service.shutdown(); }

最后實(shí)現(xiàn)main方法,用線程池來提交10次線程任務(wù)。結(jié)果我們發(fā)現(xiàn),這個(gè)靜態(tài)變量會(huì)出現(xiàn)重復(fù)(并不是每一次運(yùn)行都會(huì)重復(fù))

線程名pool-2-thread-1訂單號(hào):20180719619072331
線程名pool-2-thread-7訂單號(hào):20180719619072337
線程名pool-2-thread-3訂單號(hào):20180719619072337
線程名pool-2-thread-9訂單號(hào):20180719619072336
線程名pool-2-thread-5訂單號(hào):20180719619072335
線程名pool-2-thread-6訂單號(hào):20180719619072334
線程名pool-2-thread-10訂單號(hào):20180719619072333
線程名pool-2-thread-4訂單號(hào):20180719619072330
線程名pool-2-thread-2訂單號(hào):20180719619072332
線程名pool-2-thread-8訂單號(hào):20180719619072338

由此我們可以斷定,對(duì)象鎖并不能保證靜態(tài)變量的同步安全。不過如果對(duì)象在堆內(nèi)存中是唯一的,如

public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final CountDownLatch latch = new CountDownLatch(1); OrderService orderService = new OrderLockServiceImpl(); for (int i = 0;i < 10;i++) {service.submit(new OrderTask(latch,orderService)); }latch.countDown(); service.shutdown(); }

則無論你運(yùn)行多少次,則靜態(tài)變量也一定是同步的。

但是如果我們使用的是類鎖,來改進(jìn)上面的代碼。

public abstract class AbstractOrderService implements OrderService {static int num = 0; public static synchronized String getOrderNo2() {SimpleDateFormat date = new SimpleDateFormat("YYYYMMDDHHMMSS"); return date.format(new Date()) + num++; }@Override public String getOrderNo() {return getOrderNo2(); } }

抽象類中使用靜態(tài)方法,來同步靜態(tài)變量。

public class OrderLockServiceImpl extends AbstractOrderService {}

我們?cè)谧宇愔惺裁炊疾蛔?#xff0c;只繼承于抽象類

此時(shí)我們即便實(shí)例化10個(gè)對(duì)象

for (int i = 0;i < 10;i++) {OrderService orderService = new OrderLockServiceImpl(); service.submit(new OrderTask(latch,orderService)); }

其結(jié)果依然無論運(yùn)行多少次,都不會(huì)出現(xiàn)重復(fù)訂單號(hào),因?yàn)檫@里已經(jīng)使用了類鎖來同步靜態(tài)變量。

轉(zhuǎn)載于:https://my.oschina.net/u/3768341/blog/1854233

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的静态变量的多线程同步问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。