Java線程同步的方法

線程的同步是Java多線程編程的難點,往往開發者搞不清楚什麼是競爭資源、什麼時候需要考慮同步,怎麼同步等等問題,當然,這些問題沒有很明確的答案,但有些原則問題需要考慮,是否有競爭資源被同時改動的問題?以下僅供參考!

Java線程同步的方法

對於同步,在具體的Java代碼中需要完成一下兩個操作:把競爭訪問的資源標識爲private;同步哪些修改變量的代碼,使用synchronized關鍵字同步方法或代碼。當然這不是唯一控制併發安全的途徑。synchronized關鍵字使用說明synchronized只能標記非抽象的方法,不能標識成員變量。爲了演示同步方法的使用,構建了一個信用卡賬戶,起初信用額爲100w,然後模擬透支、存款等多個操作。顯然銀行賬戶User對象是個競爭資源,而多個併發操作的是賬戶方法oper(int x),當然應該在此方法上加上同步,並將賬戶的餘額設爲私有變量,禁止直接訪問。

/**

* Java線程:線程的同步

*

* @author leizhimin 2009-11-4 11:23:32

*/

public class Test {

public static void main(String[] args) {

User u = new User(“張三”, 100);

MyThread t1 = new MyThread(“線程A”, u, 20);

MyThread t2 = new MyThread(“線程B”, u, -60);

MyThread t3 = new MyThread(“線程C”, u, -80);

MyThread t4 = new MyThread(“線程D”, u, -30);

MyThread t5 = new MyThread(“線程E”, u, 32);

MyThread t6 = new MyThread(“線程F”, u, 21);

t();

t();

t();

t();

t();

t();

}

}

class MyThread extends Thread {

private User u;

private int y = 0;

MyThread(String name, User u, int y) {

super(name);

this.u = u;

this.y = y;

}

public void run() {

(y);

}

}

class User {

private String code;

private int cash;

User(String code, int cash) {

= code;

= cash;

}

public String getCode() {

return code;

}

public void setCode(String code) {

= code;

}

/**

* 業務方法

* @param x 添加x萬元

*/

public synchronized void oper(int x) {

try {

p(10L);

+= x;

tln(entThread()。getName() + “運行結束,增加” + x + “”,“當前用戶賬戶餘額爲:” + cash);

p(10L);

} catch (InterruptedException e) {

tStackTrace();

}

}

@Override

public String toString() {

return “User{” + “code=‘” + code + ’‘’ + “, cash=” + cash +‘}’;

}

}

輸出結果:線程A運行結束,增加“20”,當前用戶賬戶餘額爲:120.

線程F運行結束,增加“21”,當前用戶賬戶餘額爲:141.

線程E運行結束,增加“32”,當前用戶賬戶餘額爲:173.

線程C運行結束,增加“-80”,當前用戶賬戶餘額爲:93.

線程B運行結束,增加“-60”,當前用戶賬戶餘額爲:33.

線程D運行結束,增加“-30”,當前用戶賬戶餘額爲:3.

Process finished with exit code 0反面教材,不同步的情況,也就是去掉oper(int x)方法的synchronized修飾符,然後運行程序,結果如下:線程A運行結束,增加“20”,當前用戶賬戶餘額爲:61.

線程D運行結束,增加“-30”,當前用戶賬戶餘額爲:63.

線程B運行結束,增加“-60”,當前用戶賬戶餘額爲:3.

線程F運行結束,增加“21”,當前用戶賬戶餘額爲:61.

線程E運行結束,增加“32”,當前用戶賬戶餘額爲:93.

線程C運行結束,增加“-80”,當前用戶賬戶餘額爲:61.

Process finished with exit code 0很顯然,上面的結果是錯誤的,導致錯誤的原因是多個線程併發訪問了競爭資源u,並對u的屬性做了改動。可見同步的重要性。注意:通過前文可知,線程退出同步方法時將釋放掉方法所屬對象的鎖,但還應該注意的是,同步方法中還可以使用特定的方法對線程進行調度。這些方法來自於ct類,void notify()。

喚醒在此對象監視器上等待的`單個線程。

void notifyAll()

喚醒在此對象監視器上等待的所有線程。

void wait()

導致當前的線程等待,直到其他線程調用此對象的 notify() 方法或 notifyAll() 方法。

void wait(long timeout)

導致當前的線程等待,直到其他線程調用此對象的 notify() 方法或 notifyAll() 方法,或者超過指定的時間量。

void wait(long timeout, int nanos)

導致當前的線程等待,直到其他線程調用此對象的 notify() 方法或 notifyAll() 方法,或者其他某個線程中斷當前線程,或者已超過某個實際時間量。