本文實例講述了java線程同步操作。分享給大家供大家參考,具體如下:
java線程同步
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class hello { public static void main(string[] args) { myrun myrun0 = new myrun(); new thread(myrun0, "thread0" ).start(); new thread(myrun0, "thread1" ).start(); new thread(myrun0, "thread2" ).start(); } } class myrun implements runnable { private int k = 0 ; @override public void run() { for ( int i = 0 ; i < 3 ; i++) { system.out.println(thread.currentthread().getname() + "**********" + i); k++; if (k <= 3 ) { if ( "thread0" .equals(thread.currentthread().getname())) { try { thread.sleep( 100 ); } catch (interruptedexception e) { e.printstacktrace(); } } system.out.println(thread.currentthread().getname() + "," + k); } } } } |
輸出結(jié)果
thread0**********0
thread1**********0
thread2**********0
thread1,2
thread2,3
thread1**********1
thread2**********1
thread2**********2
thread1**********2
thread0,7
thread0**********1
thread0**********2
說明多線程在某些場景是存在問題的,有時候需要線程同步。
同步 synchronized
同步代碼塊,synchronized(obj){}
,obj是一個對象,在這里就相當(dāng)于一把鎖,表示一旦有進程搶到了這把鎖的鑰匙(就是進入了代碼塊),其他進程將無法進入該鎖的代碼塊(當(dāng)前代碼塊其他進程一定是進不來了,其他地方的代碼塊如果也是用了這把鎖,同樣進不去),只有代碼塊執(zhí)行完,釋放鎖后,所有進程再重新?lián)岃€匙。
注意,上同一把鎖的代碼塊都會被鎖住,這些代碼塊可能寫在不同方法不同位置上。
被同步代碼塊包住的代碼多個線程只能順次進入。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
synchronized ( this ) { k++; if (k <= 3 ) { if ( "thread0" .equals(thread.currentthread().getname())) { try { thread.sleep( 100 ); } catch (interruptedexception e) { e.printstacktrace(); } } system.out.println(thread.currentthread().getname() + "," + k); } } |
this
表示當(dāng)前對象,這里考慮的只是運行這個方法,不涉及其它類也不涉及這個類的其它地方需要同步問題,所以用this
也是可以的。k增加和輸出一個流程內(nèi)只能有一個線程在訪問,所以可以得到想要的輸出結(jié)果
輸出結(jié)果
thread0**********0
thread1**********0
thread2**********0
thread0,1
thread0**********1
thread2,2
thread2**********1
thread1,3
thread1**********1
thread0**********2
thread2**********2
thread1**********2
對方法進行同步,如果存在多線程,每個線程順次訪問該方法
注意,如果一個類里面存在多個同步方法,那么這些同步方法的鎖是一個,都是當(dāng)前對象,所以不同線程想同時訪問同一對象的不同方法也是不行的,因為這些方法都上了同一把鎖,但是鑰匙只有一把,只能一個線程持有。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@override public synchronized void run() { for ( int i = 0 ; i < 3 ; i++) { system.out.println(thread.currentthread().getname() + "**********" + i); k++; if (k <= 3 ) { if ( "thread0" .equals(thread.currentthread().getname())) { try { thread.sleep( 100 ); } catch (interruptedexception e) { e.printstacktrace(); } } system.out.println(thread.currentthread().getname() + "," + k); } } } |
輸出結(jié)果
thread0**********0
thread0,1
thread0**********1
thread0,2
thread0**********2
thread0,3
thread2**********0
thread2**********1
thread2**********2
thread1**********0
thread1**********1
thread1**********2
死鎖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
public class hello { public static void main(string[] args) { a a = new a(); b b = new b(); new thread( new myrun(a,b)).start(); new thread( new myrun1(a,b)).start(); } } class myrun implements runnable{ private a a; private b b; public myrun(a a, b b) { this .a = a; this .b = b; } @override public void run(){ a.say(b); } } class myrun1 implements runnable { private a a; private b b; public myrun1(a a, b b) { this .a = a; this .b = b; } @override public void run() { b.say(a); } } class a{ public synchronized void say(b b){ system.out.println( "a要知道b的信息" ); b.info(); } public synchronized void info(){ system.out.println( "這是a" ); } } class b{ public synchronized void say(a a){ system.out.println( "b要知道a的信息" ); a.info(); } public synchronized void info(){ system.out.println( "這是b" ); } } |
如果兩個線程同時進入了兩個say方法,就是出現(xiàn)死鎖。
關(guān)鍵點在于一個對象的多個同步方法具有相同的鎖,都是當(dāng)前對象。也就是x線程在訪問a對象的say方法過程中,y線程是無法訪問a對象的info方法的,因為開鎖的鑰匙已經(jīng)被x線程搶占了。
上面的程序,如果線程x,y同時進入了兩個say方法,a對象同步方法的鎖被線程x搶占,b對象同步方法的鎖被線程y搶占,此時線程x無法訪問b對象的同步方法,線程y無法訪問a對象的同步方法。代碼中恰好想要訪問,所以就出現(xiàn)死鎖了。
希望本文所述對大家java程序設(shè)計有所幫助。
原文鏈接:https://blog.csdn.net/shuair/article/details/81906040