在線程程序開發過程中,當要考慮到併發問題時,常常需要用到同步技術,比如在開發銀行轉賬系統或者是汽車售票系統這種對於數據的實時性和原子性有所要求的場合的時候,同步技術必不可少。
這裏以同時開兩個線程各自逐個打印不同的名字爲例,運行程序時,若不使用同步時,可能會出現亂序的情況,使用同步則可以保證正確的打印順序。
示例代碼如下:
public class TraditionalThreadSynchronized {
/**
* @param args
*/
public static void main(String[] args) {
final Output output = new Output();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
output.output1("李逍遙");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
output.output1("張三丰");
}
}
}).start();
}
}
/**
* ①②兩方法等價
* ③④兩方法等價
* @author Administrator
*
*/
class Output{
// 沒有使用同步
public void output0(String str){
int len = str.length();
for (int i = 0; i < len; i++) {
System.out.print(str.charAt(i));
}
}
// ①
public void output1(String str){
int len = str.length();
synchronized (this) {
for (int i = 0; i < len; i++) {
System.out.print(str.charAt(i));
}
System.out.println();
}
}
// ②
public synchronized void output2(String str){
int len = str.length();
for (int i = 0; i < len; i++) {
System.out.print(str.charAt(i));
}
System.out.println();
}
// ③
public static synchronized void output3(String str){
int len = str.length();
for (int i = 0; i < len; i++) {
System.out.print(str.charAt(i));
}
System.out.println();
}
// ④
public void output4(String str){
int len = str.length();
synchronized (Output.class) {
for (int i = 0; i < len; i++) {
System.out.print(str.charAt(i));
}
System.out.println();
}
}
}
①②③④各方法單獨使用都可以實現同步,區別如下:代碼中的Output類的①②兩方法是等價的,都是以Output自身作爲同步鎖
代碼中的Output類的③④兩方法是等價的,都是以Output的字節碼作爲同步鎖,由於④方法是靜態的,在被調用時候Output並沒有被實例化,但其字節碼對象已被創建,故它和③方法用的是同樣的鎖。