javamutex
① java 多核處理器下會發生同時獲取對象鎖的情況嗎
對象鎖類鎖
對象鎖
當一個對象中有synchronized method或synchronized block的時候調用此對象的同步方法或進入其同步區域時,就必須先獲得對象鎖。如果此對象的對象鎖已被其他調用者佔用,則需要等待此鎖被釋放
同步靜態方法/靜態變數互斥體
由於一個class不論被實例化多少次,其中的靜態方法和靜態變數在內存中都只由一份。所以,一旦一個靜態的方法被申明為synchronized。此類所有的實例化對象在調用此方法,共用同一把鎖,我們稱之為類鎖。一旦一個靜態變數被作為synchronized block的mutex。進入此同步區域時,都要先獲得此靜態變數的對象鎖
類鎖
由上述同步靜態方法引申出一個概念,那就是類鎖。其實系統中並不存在什麼類鎖。當一個同步靜態方法被調用時,系統獲取的其實就是代表該類的類對象的對象鎖
在程序中獲取類鎖
可以嘗試用以下方式獲取類鎖
synchronized (xxx.class) {}
synchronized (Class.forName("xxx")) {}
同時獲取2類鎖
同時獲取類鎖和對象鎖是允許的,並不會產生任何問題,但使用類鎖時一定要注意,一旦產生類鎖的嵌套獲取的話,就會產生死鎖,因為每個class在內存中都只能生成一個Class實例對象。
② JAVA模擬生產者與消費者實例
使用的生產者和消費者模型具有如下特點:
(1)本實驗的多個緩沖區不是環形循環的,也不要求按順序訪問。生產者可以把產品放到目前某一個空緩沖區中。
(2)消費者只消費指定生產者的產品。
(3)在測試用例文件中指定了所有的生產和消費的需求,只有當共享緩沖區的數據滿足了所有關於它的消費需求後,此共享緩沖區才可以作為空閑空間允許新的生產者使用。
(4)本實驗在為生產者分配緩沖區時各生產者間必須互斥,此後各個生產者的具體生產活動可以並發。而消費者之間只有在對同一產品進行消費時才需要互斥,同時它們在消費過程結束時需要判斷該消費對象是否已經消費完畢並清除該產品。
Windows
用來實現同步和互斥的實體。在Windows
中,常見的同步對象有:信號量(Semaphore)、
互斥量(Mutex)、臨界段(CriticalSection)和事件(Event)等。本程序中用到了前三個。使用這些對象都分
為三個步驟,一是創建或者初始化:接著請求該同步對象,隨即進入臨界區,這一步對應於互斥量的
上鎖;最後釋放該同步對象,這對應於互斥量的解鎖。這些同步對象在一個線程中創建,在其他線程
中都可以使用,從而實現同步互斥。當然,在進程間使用這些同步對象實現同步的方法是類似的。
1.用鎖操作原語實現互斥
為解決進程互斥進人臨界區的問題,可為每類臨界區設置一把鎖,該鎖有打開和關閉兩種狀態,進程執行臨界區程序的操作按下列步驟進行:
①關鎖。先檢查鎖的狀態,如為關閉狀態,則等待其打開;如已打開了,則將其關閉,繼續執行步驟②的操作。
②執行臨界區程序。
③開鎖。將鎖打開,退出臨界區。
2.信號量及WAIT,SIGNAL操作原語
信號量的初值可以由系統根據資源情況和使用需要來確定。在初始條件下信號量的指針項可以置為0,表示隊列為空。信號量在使用過程中它的值是可變的,但只能由WAIT,SIGNAL操作來改變。設信號量為S,對S的WAIT操作記為WAIT(S),對它的SIGNAL操作記為SIGNAL(S)。
WAIT(S):順序執行以下兩個動作:
①信號量的值減1,即S=S-1;
②如果S≥0,則該進程繼續執行;
如果
S(0,則把該進程的狀態置為阻塞態,把相應的WAITCB連人該信號量隊列的末尾,並放棄處理機,進行等待(直至其它進程在S上執行SIGNAL操作,把它釋放出來為止)。
SIGNAL(S):順序執行以下兩個動作
①S值加
1,即
S=S+1;
②如果S)0,則該進程繼續運行;
如果S(0則釋放信號量隊列上的第一個PCB(既信號量指針項所指向的PCB)所對應的進程(把阻塞態改為就緒態),執行SIGNAL操作的進程繼續運行。
在具體實現時注意,WAIT,SIGNAL操作都應作為一個整體實施,不允許分割或相互穿插執行。也就是說,WAIT,SIGNAL操作各自都好像對應一條指令,需要不間斷地做下去,否則會造成混亂。
從物理概念上講,信號量S)時,S值表示可用資源的數量。執行一次WAIT操作意味著請求分配一個單位資源,因此S值減1;當S<0時,表示已無可用資源,請求者必須等待別的進程釋放了該類資源,它才能運行下去。所以它要排隊。而執行一次SIGNAL操作意味著釋放一個單位資源,因此S值加1;若S(0時,表示有某些進程正在等待該資源,因而要把隊列頭上的進程喚醒,釋放資源的進程總是可以運行下去的。
---------------
/**
*
生產者
*
*/
public
class
Procer
implements
Runnable{
private
Semaphore
mutex,full,empty;
private
Buffer
buf;
String
name;
public
Procer(String
name,Semaphore
mutex,Semaphore
full,Semaphore
empty,Buffer
buf){
this.mutex
=
mutex;
this.full
=
full;
this.empty
=
empty;
this.buf
=
buf;
this.name
=
name;
}
public
void
run(){
while(true){
empty.p();
mutex.p();
System.out.println(name+"
inserts
a
new
proct
into
"+buf.nextEmptyIndex);
buf.nextEmptyIndex
=
(buf.nextEmptyIndex+1)%buf.size;
mutex.v();
full.v();
try
{
Thread.sleep(1000);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
}
}
}
---------------
/**
*
消費者
*
*/
public
class
Customer
implements
Runnable{
private
Semaphore
mutex,full,empty;
private
Buffer
buf;
String
name;
public
Customer(String
name,Semaphore
mutex,Semaphore
full,Semaphore
empty,Buffer
buf){
this.mutex
=
mutex;
this.full
=
full;
this.empty
=
empty;
this.buf
=
buf;
this.name
=
name;
}
public
void
run(){
while(true){
full.p();
mutex.p();
System.out.println(name+"
gets
a
proct
from
"+buf.nextFullIndex);
buf.nextFullIndex
=
(buf.nextFullIndex+1)%buf.size;
mutex.v();
empty.v();
try
{
Thread.sleep(1000);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
}
}
}
-------------------------
/**
*
緩沖區
*
*/
public
class
Buffer{
public
Buffer(int
size,int
nextEmpty,int
nextFull){
this.nextEmptyIndex
=
nextEmpty;
this.nextFullIndex
=
nextFull;
this.size
=
size;
}
public
int
size;
public
int
nextEmptyIndex;
public
int
nextFullIndex;
}
-----------------
/**
*
此類用來模擬信號量
*
*/
public
class
Semaphore{
private
int
semValue;
public
Semaphore(int
semValue){
this.semValue
=
semValue;
}
public
synchronized
void
p(){
semValue--;
if(semValue<0){
try
{
this.wait();
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
}
}
public
synchronized
void
v(){
semValue++;
if(semValue<=0){
this.notify();
}
}
}
------------------------
public
class
Test
extends
Thread
{
public
static
void
main(String[]
args)
{
Buffer
bf=new
Buffer(10,0,0);
Semaphore
mutex=new
Semaphore(1);
Semaphore
full=new
Semaphore(0);
Semaphore
empty=new
Semaphore(10);
//new
Thread(new
Procer("p001",mutex,full,empty,bf)).start();
Procer
p=new
Procer("p001",mutex,full,empty,bf);
new
Thread(new
Procer("p002",mutex,full,empty,bf)).start();
new
Thread(new
Procer("p003",mutex,full,empty,bf)).start();
new
Thread(new
Procer("p004",mutex,full,empty,bf)).start();
new
Thread(new
Procer("p005",mutex,full,empty,bf)).start();
try{
sleep(3000);
}
catch(Exception
ex)
{
ex.printStackTrace();
}
new
Thread(new
Customer("c001",mutex,full,empty,bf)).start();
new
Thread(new
Customer("c002",mutex,full,empty,bf)).start();
new
Thread(new
Customer("c003",mutex,full,empty,bf)).start();
new
Thread(new
Customer("c004",mutex,full,empty,bf)).start();
new
Thread(new
Customer("c005",mutex,full,empty,bf)).start();
}
}
--------------------------------------------
③ java 如何判斷一個線程結束
線程結束時等待也就結束了
------解決方案--------------------------------------------------------
waitforsingleobject當然可以。
或者設一全局變數,線程結束就將其置為某值。在別處讀取該值,就可以判斷線程是否結束了。
------解決方案--------------------------------------------------------
wait_object_0
表示這個線程已經退出了,wait_timeout是這個線程在此函數返回時候還沒退出,但是設置的等待時間已經到了,wait_abandoned是所等待的對象是mutex而非thread,
④ Java如何實現線程之間的互斥
臨界區(Critical Section):適合一個進程內的多線程訪問公共區域或代碼段時使用
Java如何實現線程之間的互斥
互斥量 (Mutex):適合不同進程內多線程訪問公共區域或代碼段時使用,與臨界區相似。
事件(Event):通過線程間觸發事件實現同步互斥
信號量(Semaphore):與臨界區和互斥量不同,可以實現多個線程同時訪問公共區域數據,原理與操作系統中PV操作類似,先設置一個訪問公共區域的線程最大連接數,每有一個線程訪問共享區資源數就減一,直到資源數小於等於零。
⑤ java線程中的同步鎖和互斥鎖有什麼區別
互斥是通過競爭對資源的獨占使用,彼此之間不需要知道對方的存在,執行順序是一個亂序。
同步是協調多個相互關聯線程合作完成任務,彼此之間知道對方存在,執行順序往往是有序的。
⑥ 寫出java多線程程序設計中常用類及方法名,並分別說明它們的作用。
Thread類
System.Threading.Thread類是創建並控制線程,設置其優先順序並獲取其狀態最為常用的類
Mutex類
當兩個或更多線程需要同訪問一個共享資源時,系統需要使用同步機制來確保一次只有一個線程使用該資源。Mutex是同步基元,它只向一個線程授予對共享資源的獨占訪問權。
ReaderWriterLock類
ReaderWriterLock類定義支持單個寫線程和多個讀線程鎖,用於同步對資源的訪問。在任一特定時刻,它允許多個線程同時進行讀訪問,或者允許單個線程進行寫訪問。在資源不經常發生更改情況下,ReaderWriterLock類所提供的吞吐量比簡單的一次只允許一個線程的鎖更高。
ThreadPool類
如果有多個任務需要完成,每個任務需要一個線程,這時應該考慮使用線程池來更有效地管理計算機資源並且從中受益。線程池是執行的多個線程集合,它允許系統添加以線程自動創建和開始的任務到隊列中,使用線程池使得系統可以優化線程在CPU使用時的時間碎片。但是要記住在任何特定的時間點,每一個進程一每個線程池只有一個個正在運行的線程。使用ThreadPool類可以使得由線程組成的池可以被系統管理,而使開發人員主要精力集中在工作流的邏輯,而不是線程管理上。
WaitHandle類
WaitHandle類封裝等待共享資源的獨占訪問權的操作系統特定的對象,通常用做同步對象的基類。從該類派生的類定義一個信號傳輸機制以指示獲取或釋放對共享資源的獨占訪問,但使用繼承的WaitHandle方法在等待對共享資源的訪問時阻塞。使用此類的靜態方法阻塞刈割線程,直到一個或多個同步對象接收到信息。
AutoResetEent類
AutoResetEvent類通知正在等待的線程已發生事件,無法繼承此類。AutoResetEvent類允許線程通過發信號互相通信,通常此通信涉及線程需要獨占訪問的資源。
AutoResetEvent類將始終保持終止,直到一個正在等待的線程被釋放,此時系統將自動把狀態設置為非終止狀態。如果沒有任何線程豐等待,則狀態將保持為終止狀態。
⑦ java鎖定一個類
不用mutext、synchronized
自己的土方法
假設用戶1首先通過競爭得到類A的實例
在class a中的方法getInstance()中 設置A 的靜態變數busy=true
當其他用戶調用getInstance()的時候如果busy ==true 那麼阻塞
while(busy)
{
sleep(1)
}
或者直接返回null 讓用戶自己判斷處理
當用戶1使用完畢後,再調用A的方法來讓busy=false
public void release(Class a)
{
if(a==null)
{return;}
busy=false;
}
⑧ (java大一題目)多線程
publicclassTest{
publicstaticfinalStringmutex="XXXXXXXXX";
privatestaticintmoney=1000;
publicstaticvoidmain(String[]args){
Threadt1=newThread(newmyThread("A"));
Threadt2=newThread(newmyThread("B"));
t1.start();
t2.start();
}
{
privateStringpeople;
privateintindex=0;
privateinttotal=0;
publicmyThread(Stringpeople){
this.people=people;
}
@Override
publicvoidrun(){
while(true){
synchronized(mutex){
if(money>=0){
inta=(int)(Math.random()*1000+100)/100*100;
if(money<a){
System.out.println("余額不足");
break;
}
money-=a;
total+=a;
index++;
System.out.println(people+"第"+index+"次取"+a+"元,總共取了"+total);
}else{
break;
}
}
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
//TODO自動生成的catch塊
e.printStackTrace();
}
}
}
}
}