分类: Java
2010-07-05 21:46:09
public class Thread
public class SynchronizedCounter {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
}
上面这个类的方法很明显都是用关键字synchronized修饰过的,也就是说这些方法都会保证再相应的方法
被调用时不会有任何其它的方法被调用到。这样变量c就会总按些方法的处理进行变化,而不会出现异常。
如果把synchronized去掉,就会有各种奇怪的现象发生了。
当然了同步也可以在一个小语句块中加入。
public void addName(String name) {
synchronized(this) {
lastName = name;
nameCount++;
}
nameList.add(name);
这样,nameCount跟lastName都是相同的了,毕竟后面的nameList做为一个容器可以在多线程的环境下
可以被同时放入与取出某些内容更合乎我们世界的客观规律嘛。
Atomic Access
JAVA语言中默认支持下面的原子操作。
long
and
double
).
volatile
(including long
and
double
variables).
也就是说读写引用类型的变量 与除了long,double以后的基本类型变量是原子的操作。
而对于所有声明为volatile的变量都是原子操作。
下面是一段死锁代码。
public class Deadlock {
static class Friend {
private final String name;
public Friend(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public synchronized void bow(Friend bower) {
System.out.format("%s: %s has bowed to me!%n",
this.name, bower.getName());
bower.bowBack(this);
}
public synchronized void bowBack(Friend bower) {
System.out.format("%s: %s has bowed back to me!%n",
this.name, bower.getName());
}
}
public static void main(String[] args) {
final Friend alphonse = new Friend("Alphonse");
final Friend gaston = new Friend("Gaston");
new Thread(new Runnable() {
public void run() { alphonse.bow(gaston); }
}).start();
new Thread(new Runnable() {
public void run() { gaston.bow(alphonse); }
}).start();
}
}
显然在调用bow时,由于又调用到了bowBack,每个线程都会锁死的。因为方法给的synchronized是只有在
方法调用完成时才会解锁, 而上面的代码是在一个锁上上后,再调用一个等开锁的方法,等新方法获得锁
然后再释放锁,才能再回到bow方法再释放锁,这就是逻辑锁死。
这种代码只有在走码或是设计时避免。