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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java单线程上锁_关于Java多线程编程锁优化的深入学习

發(fā)布時(shí)間:2025/3/11 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java单线程上锁_关于Java多线程编程锁优化的深入学习 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

正文

并發(fā)環(huán)境下進(jìn)行編程時(shí),需要使用鎖機(jī)制來同步多線程間的操作,保證共享資源的互斥訪問。加鎖會帶來性能上的損壞,似乎是眾所周知的事情。然而,加鎖本身不會帶來多少的性能消耗,性能主要是在線程的獲取鎖的過程。如果只有一個(gè)線程競爭鎖,此時(shí)并不存在多線程競爭的情況,那么JVM會進(jìn)行優(yōu)化,那么這時(shí)加鎖帶來的性能消耗基本可以忽略。因此,規(guī)范加鎖的操作,優(yōu)化鎖的使用方法,避免不必要的線程競爭,不僅可以提高程序性能,也能避免不規(guī)范加鎖可能造成線程死鎖問題,提高程序健壯性。下面闡述幾種鎖優(yōu)化的思路。

一、盡量不要鎖住方法

在普通成員函數(shù)上加鎖時(shí),線程獲得的是該方法所在對象的對象鎖。此時(shí)整個(gè)對象都會被鎖住。這也意味著,如果這個(gè)對象提供的多個(gè)同步方法是針對不同業(yè)務(wù)的,那么由于整個(gè)對象被鎖住,一個(gè)業(yè)務(wù)業(yè)務(wù)在處理時(shí),其他不相關(guān)的業(yè)務(wù)線程也必須wait。下面的例子展示了這種情況:

LockMethod類包含兩個(gè)同步方法,分別在兩種業(yè)務(wù)處理中被調(diào)用:

public class LockMethod {

public synchronized void busiA() {

for (int i = 0; i < 10000; i++) {

System.out.println(Thread.currentThread().getName() + "deal with bussiness A:"+i);

}

}

public synchronized void busiB() {

for (int i = 0; i < 10000; i++) {

System.out.println(Thread.currentThread().getName() + "deal with bussiness B:"+i);

}

}

}

BUSSA是線程類,用來處理A業(yè)務(wù),調(diào)用的是LockMethod的busiA()方法:

public class BUSSB extends Thread {

LockMethod lockMethod;

void deal(LockMethod lockMethod){

this.lockMethod = lockMethod;

}

@Override

public void run() {

super.run();

lockMethod.busiB();

}

}

TestLockMethod類,使用線程BUSSA與BUSSB進(jìn)行業(yè)務(wù)處理:

public class TestLockMethod extends Thread {

public static void main(String[] args) {

LockMethod lockMethod = new LockMethod();

BUSSA bussa = new BUSSA();

BUSSB bussb = new BUSSB();

bussa.deal(lockMethod);

bussb.deal(lockMethod);

bussa.start();

bussb.start();

}

}

運(yùn)行程序,可以看到在線程bussa 執(zhí)行的過程中,bussb是不能夠進(jìn)入函數(shù) busiB()的,因?yàn)榇藭r(shí)lockMethod 的對象鎖被線程bussa獲取了。

二、縮小同步代碼塊,只鎖數(shù)據(jù)

有時(shí)候?yàn)榱司幊谭奖?#xff0c;有些人會synchnoized很大的一塊代碼,如果這個(gè)代碼塊中的某些操作與共享資源并不相關(guān),那么應(yīng)當(dāng)把它們放到同步塊外部,避免長時(shí)間的持有鎖,造成其他線程一直處于等待狀態(tài)。尤其是一些循環(huán)操作、同步I/O操作。不止是在代碼的行數(shù)范圍上縮小同步塊,在執(zhí)行邏輯上,也應(yīng)該縮小同步塊,例如多加一些條件判斷,符合條件的再進(jìn)行同步,而不是同步之后再進(jìn)行條件判斷,盡量減少不必要的進(jìn)入同步塊的邏輯。

三、鎖中盡量不要再包含鎖

這種情況經(jīng)常發(fā)生,線程在得到了A鎖之后,在同步方法塊中調(diào)用了另外對象的同步方法,獲得了第二個(gè)鎖,這樣可能導(dǎo)致一個(gè)調(diào)用堆棧中有多把鎖的請求,多線程情況下可能會出現(xiàn)很復(fù)雜、難以分析的異常情況,導(dǎo)致死鎖的發(fā)生。下面的代碼顯示了這種情況:

synchronized(A){

synchronized(B){

}

}

或是在同步塊中調(diào)用了同步方法:

synchronized(A){

B b = objArrayList.get(0);

b.method(); //這是一個(gè)同步方法

}

解決的辦法是跳出來加鎖,不要包含加鎖:

{

B b = null;

synchronized(A){

b = objArrayList.get(0);

}

b.method();

}

四、將鎖私有化,在內(nèi)部管理鎖

把鎖作為一個(gè)私有的對象,外部不能拿到這個(gè)對象,更安全一些。對象可能被其他線程直接進(jìn)行加鎖操作,此時(shí)線程便持有了該對象的對象鎖,例如下面這種情況:

class A {

public void method1() {

}

}

class B {

public void method1() {

A a = new A();

synchronized (a) { //直接進(jìn)行加鎖      a.method1();

}

}

}

這種使用方式下,對象a的對象鎖被外部所持有,讓這把鎖在外部多個(gè)地方被使用是比較危險(xiǎn)的,對代碼的邏輯流程閱讀也造成困擾。一種更好的方式是在類的內(nèi)部自己管理鎖,外部需要同步方案時(shí),也是通過接口方式來提供同步操作:

class A {

private Object lock = new Object();

public void method1() {

synchronized (lock){

}

}

}

class B {

public void method1() {

A a = new A();

a.method1();

}

}

五、進(jìn)行適當(dāng)?shù)逆i分解

考慮下面這段程序:

public class GameServer {

public Map> tables = new HashMap>();

public void join(Player player, Table table) {

if (player.getAccountBalance() > table.getLimit()) {

synchronized (tables) {

List tablePlayers = tables.get(table.getId());

if (tablePlayers.size() < 9) {

tablePlayers.add(player);

}

}

}

}

public void leave(Player player, Table table) {/*省略*/}

public void createTable() {/*省略*/}

public void destroyTable(Table table) {/*省略*/}

}

在這個(gè)例子中,join方法只使用一個(gè)同步鎖,來獲取tables中的List對象,然后判斷玩家數(shù)量是不是小于9,如果是,就調(diào)增加一個(gè)玩家。當(dāng)有成千上萬個(gè)List存在tables中時(shí),對tables鎖的競爭將非常激烈。在這里,我們可以考慮進(jìn)行鎖的分解:快速取出數(shù)據(jù)之后,對List對象進(jìn)行加鎖,讓其他線程可快速競爭獲得tables對象鎖:

public class GameServer {

public Map < String,

List < Player >> tables = new HashMap < String,

List < Player >> ();

public void join(Player player, Table table) {

if (player.getAccountBalance() > table.getLimit()) {

List < Player > tablePlayers = null;

synchronized(tables) {

tablePlayers = tables.get(table.getId());

}

synchronized(tablePlayers) {

if (tablePlayers.size() < 9) {

tablePlayers.add(player);

}

}

}

}

public void leave(Player player, Table table) {

/*省略*/

}

public void createTable() {

/*省略*/

}

public void destroyTable(Table table) {

/*省略*/

}

}

總結(jié)

以上是生活随笔為你收集整理的java单线程上锁_关于Java多线程编程锁优化的深入学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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