一
線程的同步是為了防止多個線程訪問一個數據對象時
例如
public class Foo {
private int x =
public int getX() {
return x;
}
public int fix(int y) {
x = x
return x;
}
}
public class MyRunnable implements Runnable {
private Foo foo = new Foo()
public static void main(String[] args) {
MyRunnable r = new MyRunnable()
Thread ta = new Thread(r
Thread tb = new Thread(r
ta
tb
}
public void run() {
for (int i =
this
try {
Thread
} catch (InterruptedException e) {
e
}
System
}
}
public int fix(int y) {
return foo
}
}
運行結果
Thread
Thread
Thread
Thread
Thread
Thread
Process finished with exit code
從結果發現
如果要保持結果的合理性
在具體的Java代碼中需要完成一下兩個操作
把競爭訪問的資源類Foo變量x標識為private;
同步哪些修改變量的代碼
二
Java中每個對象都有一個內置鎖
當程序運行到非靜態的synchronized同步方法上時
當程序運行到synchronized同步方法或代碼塊時才該對象鎖才起作用
一個對象只有一個鎖
釋放鎖是指持鎖線程退出了synchronized同步方法或代碼塊
關於鎖和同步
public int fix(int y) {
synchronized (this) {
x = x
}
return x;
}
當然
public synchronized int getX() {
return x++;
}
與
public int getX() {
synchronized (this) {
return x;
}
}
效果是完全一樣的
三
要同步靜態方法
例如
public static synchronized int setName(String name){
Xxx
}
等價於
public static int setName(String name){
synchronized(Xxx
Xxx
}
}
四
如果線程試圖進入同步方法
當考慮阻塞時
五
在多個線程同時訪問互斥(可交換)數據時
對於非靜態字段中可更改的數據
對於靜態字段中可更改的數據
如果需要在非靜態方法中使用靜態字段
六
當一個類已經很好的同步以保護它的數據時
即使是線程安全類
舉個形象的例子
看個代碼
public class NameList {
private List nameList = Collections
public void add(String name) {
nameList
}
public String removeFirst() {
if (nameList
return (String) nameList
} else {
return null;
}
}
}
public class Test {
public static void main(String[] args) {
final NameList nl = new NameList()
nl
class NameDropper extends Thread{
public void run(){
String name = nl
System
}
}
Thread t
Thread t
t
t
}
}
雖然集合對象
private List nameList = Collections
是同步的
出現這種事件的原因是
解決上面問題的辦法是
public class NameList {
private List nameList = Collections
public synchronized void add(String name) {
nameList
}
public synchronized String removeFirst() {
if (nameList
return (String) nameList
} else {
return null;
}
}
}
這樣
七
死鎖對Java程序來說
還是看一個比較直觀的死鎖例子
public class DeadlockRisk {
private static class Resource {
public int value;
}
private Resource resourceA = new Resource()
private Resource resourceB = new Resource()
public int read() {
synchronized (resourceA) {
synchronized (resourceB) {
return resourceB
}
}
}
public void write(int a
synchronized (resourceB) {
synchronized (resourceA) {
resourceA
resourceB
}
}
}
}
假設read()方法由一個線程啟動
實際上
但是
八
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27281.html