1. java語言包含兩哪些同步機制
Java 語言包含兩種內在的同步機制(都是為了實現代碼線程的安全性):
(1)同步塊(或方法)。即被synchronized修飾的變數和方法。
(2)volatile 變數。Volatile 變數的同步性較差(但有時它更簡單並且開銷更低),而且其使用也更容易出錯。Java 語言中的 volatile 變數可以被看作是一種 「程度較輕的synchronized」;與synchronized塊相比,volatile 變數所需的編碼較少,並且運行時開銷也較少,但是它所能實現的功能也僅是synchronized的一部分。
正確使用volatile的條件:
對變數的寫操作不依賴於當前值。 該變數沒有包含在具有其他變數的不變式中。
條件解釋:
在使用volatile關鍵字時要慎 重,並不是只要簡單類型變數使用volatile修飾,對這個變數的所有操作都是原來操作,當變數的值由自身的上一個決定時,如n=n+1、n++ 等,volatile關鍵字將失效,只有當變數的值和自身上一個值無關時對該變數的操作才是原子級別的,如n = m + 1,這個就是原級別的。所以在使用volatile關鍵時一定要謹慎,如果自己沒有把握,可以使用synchronized來代替volatile。
2. java中同步和非同步有什麼異同
Java中交互方式分為同步和非同步兩種:
相同的地方:
都屬於交互方式,都是發送請求。
不同的地方:
同步交互:指發送一個請求,需要等待返回,然後才能夠發送下一個請求,有個等待過程;
非同步交互:指發送一個請求,不需要等待返回,隨時可以再發送下一個請求,即不需要等待。區別:一個需要等待,一個不需要等待,在部分情況下,我們的項目開發中都會優先選擇不需要等待的非同步交互方式。
Java,是由Sun Microsystems公司於1995年5月推出的Java程序設計語言和Java平台的總稱。用Java實現的HotJava瀏覽器(支持Java applet)顯示了Java的魅力:跨平台、動態的Web、Internet計算。從此,Java被廣泛接受並推動了Web的迅速發展,常用的瀏覽器現均支持Java applet
Java是一種簡單的,面向對象的,分布式的,解釋型的,健壯安全的,結構中立的,可移植的,性能優異、多線程的動態語言。
當1995年SUN推出Java語言之後,全世界的目光都被這個神奇的語言所吸引。那麼Java到底有何神奇之處呢?
Java語言其實最早誕生於1991年,起初被稱為OAK語言,是SUN公司為一些消費性電子產品而設計的一個通用環境。他們最初的目的只是為了開發一種獨立於平台的軟體技術,而且在網路出現之前,OAK可以說是默默無聞,甚至差點夭折。但是,網路的出現改變了OAK的命運。
3. java同步和非同步的區別
java同步和非同步的區別如下:
一、根據情況需要專門的線程方式
如果數據將在線程間共享.例如正在寫的數據以後可能被另一個線程讀到,或者正在讀的數據可能已經被另一個線程寫過了,那麼這些數據就是共享數據,必須進行同步存取.
當應用程序在對象上調用了一個需要花費很長時間來執行的方法,並且不希望讓程序等待方法的返回時,就應該使用非同步編程,在很多情況下採用非同步途徑往往更有效率.
二、應用不同:
Java同步:
基本概念:每個Object都會有1個鎖.同步就是串列使用一些資源.
(說明:以下有些例子為了突出重點,省略了不必要的代碼.非凡是省掉了一些成員變數,就是需要同步的對象.)
1. 多線程中對共享、可變的數據進行同步.
對於函數中的局部變數沒必要進行同步.
對於不可變數據,也沒必要進行同步.
多線程中訪問共享可變數據才有必要.
2. 單個線程中可以使用synchronized,而且可以嵌套,但無意義.
class Test {
public static void main(String[] args) {
Test t = new Test();
synchronized(t) {
synchronized(t) {
System.out.println("ok!");
}
}
}
}
3. 對象實例的鎖
class Test{
public synchronized void f1(){
//do something here
}
public void f2(){
synchronized(this){
//do something here
}
}
}
上面的f1()和f2()效果一致, synchronized取得的鎖都是Test某個實列(this)的鎖.
比如: Test t = new Test();
線程A調用t.f2()時, 線程B無法進入t.f1(),直到t.f2()結束.
作用: 多線程中訪問Test的同一個實例的同步方法時會進行同步.
4. class的鎖
class Test{
final static Object o= new Object();
public static synchronized void f1(){
//do something here
}
public static void f2(){
synchronized(Test.class){
//do something here
}
}
public static void f3(){
try {
synchronized (Class.forName("Test")) {
//do something here
}
}
catch (ClassNotFoundException ex) {
}
}
public static void g(){
synchronized(o){
//do something here
}
}
}
上面f1(),f2(),f3(),g()效果一致
f1(),f2(),f3()中synchronized取得的鎖都是Test.class的鎖.
g()是自己產生一個對象o,利用o的鎖做同步
作用: 多線程中訪問此類或此類任一個實例的同步方法時都會同步. singleton模式lazily initializing屬於此類.
5. static method
class Test{
private static int v = 0;
public static void f1(){
//do something, 但函數中沒用用到v
}
public synchronized static void f2(){
//do something, 函數中對v進行了讀/寫.
}
}
多線程中使用Test的某個實列時,
(1) f1()是線程安全的,不需要同步
(2) f2()這個靜態方法中使用了函數外靜態變數,所以需要同步.
Java非同步:
1、 它要能適應不同類型的請求:
本節用 makeString來說明要求有返回值的請求.用displayString來說明不需要返回值的請求.
2、 要能同時並發處理多個請求,並能按一定機制調度:
本節將用一個隊列來存放請求,所以只能按FIFO機制調度,你可以改用LinkedList,就可以簡單實現一個優先順序(優先順序高的addFirst,低的addLast).
3、有能力將調用的邊界從線程擴展到機器間(RMI)
4、分離過度耦合,如分離調用句柄(取貨憑證)和真實數據的實現.分離調用和執行的過程,可以盡快地將調返回.
現在看具體的實現:
public interface Axman {
Result resultTest(int count,char c);
void noResultTest(String str);
}
這個介面有兩個方法要實現,就是有返回值的調用resultTest和不需要返回值的調用
noResultTest, 我們把這個介面用一個代理類來實現,目的是將方法調用轉化為對象,這樣就可以將多個請求(多個方法調)放到一個容器中緩存起來,然後統一處理,因為 Java不支持方法指針,所以把方法調用轉換為對象,然後在這個對象上統一執行它們的方法,不僅可以做到非同步處理,而且可以將代表方法調用的請求對象序列化後通過網路傳遞到另一個機器上執行(RMI).這也是Java回調機制最有力的實現.
一個簡單的例子.
如果 1: 做A
如果 2: 做B
如果 3: 做C
如果有1000個情況,你不至於用1000個case吧?以後再增加呢?
所以如果C/C++程序員,會這樣實現: (c和c++定義結構不同)
type define struct MyStruct{
int mark;
(*fn) ();
} MyList;
然後你可以聲明這個結構數據:
{1,A,
2,B
3,C
}
做一個循環:
for(i=0;i<length;i++) {
if(數據組[i].mark == 傳入的值) (數據組[i].*fn)();
}
簡單說c/c++中將要被調用的涵數可以被保存起來,然後去訪問,調用,而Java中,我們無法將一個方法保存,除了直接調用,所以將要調用的方法用子類來實現,然後把這些子類實例保存起來,然後在這些子類的實現上調用方法:
interface My{
void test();
}
4. java中同步和非同步有什麼異同
Java中交互方式分為同步和非同步兩種:
同步交互:指發送一個請求,需要等待返回,然後才能夠發送下一個請求,有個等待過程;
非同步交互:指發送一個請求,不需要等待返回,隨時可以再發送下一個請求,即不需要等待。
區別:一個需要等待,一個不需要等待,在部分情況下,我們的項目開發中都會優先選擇不需要等待的非同步交互方式。
哪些情況建議使用同步交互呢?比如銀行的轉賬系統,對資料庫的保存操作等等,都會使用同步交互操作,其餘情況都優先使用非同步交互。
5. java同步是什麼意思
一般有兩種方法同步方法和同步代碼塊
假設P1、P2是同一個類的不同對象,這個類中定義了以下幾種情況的同步塊或同步方法,P1、P2就都可以調用它們。
1.把synchronized當作函數修飾符時,示例代碼如下:
()
{
//….
}
這也就是同步方法,那這時synchronized鎖定的是哪個對象呢?它鎖定的是調用這個同步方法對象。也就是說,當一個對象P1在不同的線程中執行這個同步方法時,它們之間會形成互斥,達到同步的效果。但是這個對象所屬的Class所產生的另一對象P2卻可以任意調用這個被加了synchronized關鍵字的方法。
上邊的示例代碼等同於如下代碼:
publicvoidmethodAAA()
{
synchronized(this)//(1)
{
//…..
}
}
(1)處的this指的是什麼呢?它指的就是調用這個方法的對象,如P1。可見同步方法實質是將synchronized作用於objectreference。――那個拿到了P1對象鎖的線程,才可以調用P1的同步方法,而對P2而言,P1這個鎖與它毫不相干,程序也可能在這種情形下擺脫同步機制的控制,造成數據混亂:(
2.同步塊,示例代碼如下:
publicvoidmethod3(SomeObjectso)
{
synchronized(so)
{
//…..
}
}
這時,鎖就是so這個對象,誰拿到這個鎖誰就可以運行它所控制的那段代碼。當有一個明確的對象作為鎖時,就可以這樣寫程序,但當沒有明確的對象作為鎖,只是想讓一段代碼同步時,可以創建一個特殊的instance變數(它得是一個對象)來充當鎖:
classFooimplementsRunnable
{
privatebyte[]lock=newbyte[0];//特殊的instance變數
PublicvoidmethodA()
{
synchronized(lock){//…}
}
//…..
}
註:零長度的byte數組對象創建起來將比任何對象都經濟――查看編譯後的位元組碼:生成零長度的byte[]對象只需3條操作碼,而Objectlock=newObject()則需要7行操作碼。
3.將synchronized作用於static函數,示例代碼如下:
ClassFoo
{
()//同步的static函數
{
//….
}
publicvoidmethodBBB()
{
synchronized(Foo.class)//classliteral(類名稱字面常量)
}
}
代碼中的methodBBB()方法是把classliteral作為鎖的情況,它和同步的static函數產生的效果是一樣的,取得的鎖很特別,是當前調用這個方法的對象所屬的類(Class,而不再是由這個Class產生的某個具體對象了)。
記得在《EffectiveJava》一書中看到過將Foo.class和P1.getClass()用於作同步鎖還不一樣,不能用P1.getClass()來達到鎖這個Class的目的。P1指的是由Foo類產生的對象。
可以推斷:如果一個類中定義了一個synchronized的static函數A,也定義了一個synchronized的instance函數B,那麼這個類的同一對象Obj在多線程中分別訪問A和B兩個方法時,不會構成同步,因為它們的鎖都不一樣。A方法的鎖是Obj這個對象,而B的鎖是Obj所屬的那個Class。
6. Java線程同步,是什麼意思
一種是方法前加sychronized
public void sychronized start() {
System.out.println("start");
}
另一種是在代碼段之前加sychronized
(sychronized){
。。。。。
}
同步方法(synchronized關鍵字修飾的方法)可以較好地解決並發問題,在一定程度上可以避免出現資源搶占、競爭條件和死鎖的情況,但其副作用是同步鎖可導致線程阻塞。這要求同步方法的執行時間不能太長。
這就是所謂的鎖機制,你何以使用sychronized(Object obj)鎖住某個對象,等你使用完這個對象之後,再進行鎖的釋放,其他需要該對象的線程才可以執行。
7. java中非同步處理和同步處理分別是什麼意思
舉個例子:A和B一起從某點出發到終點。
同步就是只能A走完某一段然後停下,讓B開始走一段再停下,再讓A走。如此往復。簡單理解就是,必須是一段程序執行完後才能執行後面的程序。
非同步就是,同一時間可能A和B同時都在往終點趕,此時不存在先後順序,就是說,兩個程序可以同時執行,稱為非同步。
8. java 同步機制是什麼
要跨線程維護正確的可見性,只要在幾個線程之間共享非 final 變數,就必須使用 synchronized(或 volatile)以確保一個線程可以看見另一個線程做的更改。
為了在線程之間進行可靠的通信,也為了互斥訪問,同步是必須的。這歸因於java語言規范的內存模型,它規定了:一個線程所做的變化何時以及如何變成對其它線程可見。
因為多線程將非同步行為引進程序,所以在需要同步時,必須有一種方法強制進行。例如:如果2個線程想要通信並且要共享一個復雜的數據結構,如鏈表,此時需要確保它們互不沖突,也就是必須阻止B線程在A線程讀數據的過程中向鏈表裡面寫數據(A獲得了鎖,B必須等A釋放了該鎖)。
為了達到這個目的,java在一個舊的的進程同步模型——監控器(Monitor)的基礎上實現了一個巧妙的方案:監控器是一個控制機制,可以認為是一個很小的、只能容納一個線程的盒子,一旦一個線程進入監控器,其它的線程必須等待,直到那個線程退出監控為止。通過這種方式,一個監控器可以保證共享資源在同一時刻只可被一個線程使用。這種方式稱之為同步。(一旦一個線程進入一個實例的任何同步方法,別的線程將不能進入該同一實例的其它同步方法,但是該實例的非同步方法仍然能夠被調用)。
9. java 線程 「同步」是什麼意思啊
為什麼要引入同步機制
在多線程環境中,可能會有兩個甚至更多的線程試圖同時訪問一個有限的資源。必須對這種潛在資源沖突進行預防。
A調用f();那麼在A調用的時候B就不能調用了,必須等待A調用完了之後B才能調用f()。
如果想保護某些資源不被多個線程同時訪問,可以用synchronized來修飾,當某個對象用synchronized 修飾時,表明該對象在任一時刻只能由線程訪問。用法:
synchronized(myObject)
{
…
}
例:SynchronizedBlock.java
public class SynchronizedBlock implements Runnable{
public static void main(String a[]) {
SynchronizedBlock aObjSyB=new SynchronizedBlock();
Thread athread;
for(int i=0;i<3;i++)
{
athread=new Thread(aObjSyB);
athread.setPriority((int)(10*Math.random()+1));
athread.start();
}
}
public void run()
{
for(int i=0;i<=2;i++)
{
try
{
Thread.sleep(1000);
}
catch(InterruptedException e){}
synchronized(System.out)
{
System.out.print(Thread.currentThread().getName());
System.out.println(" "+i+" "+Thread.currentThread().getName());
}
}
}
}
10. java中同步和死鎖,分別是什麼樣的一個概念
同步有兩種實現方法,分別是繼承Thread
類與實現Runnable
介面;用synchronized
關鍵字修飾同步方法;suspend()方法容易發生死鎖。調用suspend()的時候,目標線程會停下來,但卻仍然持有在這之前獲得的鎖定。此時,其他任何線程都不能訪問鎖定的資源,除非被「掛起」的線程恢復運行。對任何線程來說,如果它們想恢復目標線程,同時又試圖使用任何一個鎖定的資源,就會造成死鎖。