java中同步_在Java中的方法同步和语句同步(块同步) - Break易站
Java 多線程
線程主要通過共享對字段的訪問和參考字段引用的對象進行通信。這種通信形式非常有效,但可能出現兩種錯誤:線程干擾和內存一致性錯誤。需要一些同步構造來防止這些錯誤。以下示例顯示了我們需要同步的情況。
在Java中需要同步的情況
請考慮以下示例:
// Java program to illustrate need
// of Synchronization
import java.io.*;
class Multithread
{
private int i = 0;
public void increment()
{
i++;
}
public int getValue()
{
return i;
}
}
class GfG
{
public static void main (String[] args)
{
Multithread t = new Multithread();
t.increment();
System.out.println(t.getValue());
}
}
輸出:
1
在上面的示例中,執行了三個操作:
獲取變量i的值。
增加獲取的值。
并將增加的i值存儲到其位置。
這里,
第一個線程獲取i的值。(當前值i為0)并將其增加1,因此變量i的值變為1。
現在第二個線程訪問i的值為0,因為第一個線程沒有將它存儲回它的位置。
第二個線程也會增加它并將其存儲回其位置。第1個也存儲它。
最后,變量i的值為1.但是兩個線程的效果應該是2。這就是為什么我們需要同步對共享變量i的訪問。
Java是多線程語言,其中多個線程并行運行以完成其執行。我們需要同步共享資源以確保一次只有一個線程能夠訪問共享資源。
如果一個Object由多個線程共享,則需要進行同步以避免Object的狀態被破壞。當Object是可變的時,需要同步。如果共享Object是不可變的,或者共享同一個Object的所有線程只讀取未修改的Object狀態,則不需要同步它。
Java編程語言提供兩種同步習語:
方法同步
語句同步(塊同步)
Java中的方法同步
同步方法支持一種簡單的策略來防止線程干擾和內存一致性錯誤。如果一個Object對多個線程可見,則對該Object的所有字段的讀取或寫入都是通過synchronized方法完成的。
兩次調用同步方法不可能進行交錯。如果一個線程正在執行synchronized方法,那么在同一個Object上調用synchronized方法的所有其他線程都必須等到第一個線程完成Object。
示例:這顯示了多個線程是否在沒有同步的情況下訪問getLine()方法。
// Example illustrates multiple threads are executing
// on the same Object at same time without synchronization.
import java.io.*;
class Line
{
// if multiple threads(trains) will try to
// access this unsynchronized method,
// they all will get it. So there is chance
// that Object's? state will be corrupted.
public void getLine()
{
for (int i = 0; i < 3; i++)
{
System.out.println(i);
try
{
Thread.sleep(400);
}
catch (Exception e)
{
System.out.println(e);
}
}
}
}
class Train extends Thread
{
// reference to Line's Object.
Line line;
Train(Line line)
{
this.line = line;
}
@Override
public void run()
{
line.getLine();
}
}
class GFG
{
public static void main(String[] args)
{
// Object of Line class that is shared
// among the threads.
Line obj = new Line();
// creating the threads that are
// sharing the same Object.
Train train1 = new Train(obj);
Train train2 = new Train(obj);
// threads start their execution.
train1.start();
train2.start();
}
}
輸出:
0
0
1
1
2
2
可能有兩列火車(兩個以上)需要同時使用,因此有可能發生碰撞。因此,為了避免碰撞,我們需要同步多個想要運行的行。
示例:對同一對象的getLine()方法的同步訪問
// Example that shows multiple threads
// can execute the same method but in
// synchronized way.
class Line
{
// if multiple threads(trains) trying to access
// this synchronized method on the same Object
// but only one thread will be able
// to execute it at a time.
synchronized public void getLine()
{
for (int i = 0; i < 3; i++)
{
System.out.println(i);
try
{
Thread.sleep(400);
}
catch (Exception e)
{
System.out.println(e);
}
}
}
}
class Train extends Thread
{
// Reference variable of type Line.
Line line;
Train(Line line)
{
this.line = line;
}
@Override
public void run()
{
line.getLine();
}
}
class GFG
{
public static void main(String[] args)
{
Line obj = new Line();
// we are creating two threads which share
// same Object.
Train train1 = new Train(obj);
Train train2 = new Train(obj);
// both threads start executing .
train1.start();
train2.start();
}
}
輸出:
0
1
2
0
1
2
Java中的塊同步
如果我們只需要執行一些后續代碼行而不是方法中代碼的所有行(指令),那么我們應該只同步存在所需指令的代碼塊。
例如,假設有一個方法包含100行代碼,但只有10行代碼(一個接一個)包含代碼的關鍵部分,即這些行可以修改(更改)Object的狀態。因此,我們只需要同步這10行代碼方法,以避免對Object狀態進行任何修改,并確保其他線程可以在同一方法中執行其余行而不會中斷。
import java.io.*;
import java.util.*;
public class Geek
{
String name = "";
public int count = 0;
public void geekName(String geek, List list)
{
// Only one thread is permitted
// to change geek's name at a time.
synchronized(this)
{
name = geek;
count++;? // how many threads change geek's name.
}
// All other threads are permitted
// to add geek name into list.
list.add(geek);
}
}
class GFG
{
public static void main (String[] args)
{
Geek gk = new Geek();
List list = new ArrayList();
gk.geekName("mohit", list);
System.out.println(gk.name);
}
}
輸出:
1
重點:
當線程進入同步方法或塊時,它獲取鎖定,一旦完成任務并從synchronized方法退出,它就會釋放鎖定。
當線程進入同步實例方法或塊時,它獲取對象級別鎖定,當它進入同步靜態方法或塊時,它獲取類級別鎖定。
如果在synchronized塊中使用的Object為null,則Java同步將拋出空指針異常。例如,如果在synchronized(實例)中,instance為null,則它將拋出空指針異常。
在Java中,wait(),notify()和notifyAll()是同步中使用的重要方法。
您不能將java?synchronized關鍵字應用于變量。
不要在同步塊上的非final字段上進行同步,因為對非final字段的引用可能隨時更改,然后不同的線程可能在不同的對象上同步,即根本不同步。
優點
多線程:由于java是多線程語言,因此同步是實現共享資源互斥的好方法。
實例和靜態方法:同步實例方法和同步靜態方法都可以同時執行,因為它們用于鎖定不同的對象。
限制
并發限制:?Java同步不允許并發讀取。
降低效率:?Java同步方法運行速度非常慢并且會降低性能,因此您應該在絕對必要時同步方法,否則不要同步塊僅用于代碼的關鍵部分。
總結
以上是生活随笔為你收集整理的java中同步_在Java中的方法同步和语句同步(块同步) - Break易站的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java学习视频网站_学习Java的视频
- 下一篇: java redisson_Java使用