深入同步訪問(wèn)共享的可變數(shù)據(jù)分析
更新時(shí)間:2013年06月04日 17:58:47 作者:
本篇文章是對(duì)同步訪問(wèn)共享的可變數(shù)據(jù)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
如果對(duì)共享的可變數(shù)據(jù)的訪問(wèn)不能同步,其后果非常可怕,即使這個(gè)變量是原子可讀寫的。
下面考慮一個(gè)線程同步方面的問(wèn)題。對(duì)于線程同步,Java類庫(kù)提供了Thread.stop的方法,但是這個(gè)方法并不值得提倡,因?yàn)樗举|(zhì)上是不安全的。使用輪詢(Polling)的方式會(huì)更好,例如下面這段程序。
import java.util.concurrent.TimeUnit;
public class StopThread {
/**
* @param args
*/
private static boolean stopRequested;
public static void main(String[] args)
throws InterruptedException{
Thread backgroundThread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while(!stopRequested){
i++;
System.out.println(i);
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
你可能會(huì)認(rèn)為這個(gè)程序在運(yùn)行大約一秒后,由于主線程把stopRequested設(shè)成了true,使得后臺(tái)的新線程停止,其實(shí)不然,因?yàn)楹笈_(tái)線程看不到這個(gè)值的變化,所以會(huì)一直無(wú)線循環(huán)下去,這就是沒(méi)有對(duì)數(shù)據(jù)進(jìn)行同步的后果。因此讓我們用同步的方式來(lái)實(shí)現(xiàn)這個(gè)任務(wù)。
import java.util.concurrent.TimeUnit;
public class StopThread {
/**
* @param args
*/
private static boolean stopRequested;
private static synchronized void requestStop(){
stopRequested = true;
}
private static synchronized boolean stopRequested(){
return stopRequested;
}
public static void main(String[] args)
throws InterruptedException{
Thread backgroundThread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while(!stopRequested()){
i++;
System.out.println(i);
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
requestStop();
}
}
這樣就實(shí)現(xiàn)了數(shù)據(jù)的同步,值得注意的是,寫方法(requestStop)和讀方法(stopRequested)都需要被同步,否則仍然不是真正意義上的同步。
另外,我們可以使用volatile這個(gè)變量修飾符來(lái)更加簡(jiǎn)單地完成同步任務(wù)。
import java.util.concurrent.TimeUnit;
public class StopThread {
/**
* @param args
*/
private static volatile boolean stopRequested;
public static void main(String[] args)
throws InterruptedException{
Thread backgroundThread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while(!stopRequested){
i++;
System.out.println(i);
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
下面考慮一個(gè)線程同步方面的問(wèn)題。對(duì)于線程同步,Java類庫(kù)提供了Thread.stop的方法,但是這個(gè)方法并不值得提倡,因?yàn)樗举|(zhì)上是不安全的。使用輪詢(Polling)的方式會(huì)更好,例如下面這段程序。
復(fù)制代碼 代碼如下:
import java.util.concurrent.TimeUnit;
public class StopThread {
/**
* @param args
*/
private static boolean stopRequested;
public static void main(String[] args)
throws InterruptedException{
Thread backgroundThread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while(!stopRequested){
i++;
System.out.println(i);
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
你可能會(huì)認(rèn)為這個(gè)程序在運(yùn)行大約一秒后,由于主線程把stopRequested設(shè)成了true,使得后臺(tái)的新線程停止,其實(shí)不然,因?yàn)楹笈_(tái)線程看不到這個(gè)值的變化,所以會(huì)一直無(wú)線循環(huán)下去,這就是沒(méi)有對(duì)數(shù)據(jù)進(jìn)行同步的后果。因此讓我們用同步的方式來(lái)實(shí)現(xiàn)這個(gè)任務(wù)。
復(fù)制代碼 代碼如下:
import java.util.concurrent.TimeUnit;
public class StopThread {
/**
* @param args
*/
private static boolean stopRequested;
private static synchronized void requestStop(){
stopRequested = true;
}
private static synchronized boolean stopRequested(){
return stopRequested;
}
public static void main(String[] args)
throws InterruptedException{
Thread backgroundThread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while(!stopRequested()){
i++;
System.out.println(i);
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
requestStop();
}
}
這樣就實(shí)現(xiàn)了數(shù)據(jù)的同步,值得注意的是,寫方法(requestStop)和讀方法(stopRequested)都需要被同步,否則仍然不是真正意義上的同步。
另外,我們可以使用volatile這個(gè)變量修飾符來(lái)更加簡(jiǎn)單地完成同步任務(wù)。
復(fù)制代碼 代碼如下:
import java.util.concurrent.TimeUnit;
public class StopThread {
/**
* @param args
*/
private static volatile boolean stopRequested;
public static void main(String[] args)
throws InterruptedException{
Thread backgroundThread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while(!stopRequested){
i++;
System.out.println(i);
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
相關(guān)文章
Java實(shí)現(xiàn)微信支付的項(xiàng)目實(shí)踐
最近的一個(gè)項(xiàng)目中涉及到了支付業(yè)務(wù),其中用到了微信支付和支付寶支付,本文就來(lái)介紹一下Java實(shí)現(xiàn)微信支付的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10基于Java開(kāi)發(fā)實(shí)現(xiàn)ATM系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了基于Java開(kāi)發(fā)實(shí)現(xiàn)ATM系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08解決mapper接口無(wú)法映射mapper.xml的問(wèn)題
這篇文章主要介紹了解決mapper接口無(wú)法映射mapper.xml的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06