java同步和互斥【用具体程序说明】 (一)

2014-11-24 08:12:23 · 作者: · 浏览: 2

所有对象都自动含有单一的锁,也就是所有对象都有且只有唯一的锁,所以当某个任务(线程)访问一个类A中含有sycnhronized的方法是,那么在这个线程从该方法返回之前(也就是该方法在当前线程执行完之前),类A中的其他被该关键字标记的方法在其他的线程中都会被阻塞。
通俗点说就是,当调用A的含有synchronized的方法是,A会被枷锁,此时A中其他含有synchronized方法只有等到前一个方法调用完毕释放了锁才能被调用

具体说明见另一篇博客<

下面看看具体的程序,其中,Timer中的字段num是共享资源

[java]
package com.bankht.synchronize;

public class TestSync implements Runnable {
Timer timer = new Timer();

public static void main(String[] args) {
TestSync test = new TestSync();
Thread t1 = new Thread(test);
Thread t2 = new Thread(test);
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}

public void run() {
timer.add(Thread.currentThread().getName());
}
}

class Timer {
private static int num = 0;

public void add(String name) {

num++;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
System.out.println(name + ", 你是第" + num + "个使用timer的线程");

}
}
package com.bankht.synchronize;

public class TestSync implements Runnable {
Timer timer = new Timer();

public static void main(String[] args) {
TestSync test = new TestSync();
Thread t1 = new Thread(test);
Thread t2 = new Thread(test);
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}

public void run() {
timer.add(Thread.currentThread().getName());
}
}

class Timer {
private static int num = 0;

public void add(String name) {

num++;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
System.out.println(name + ", 你是第" + num + "个使用timer的线程");

}
}

[java]
由于没有同步,所以运行结果如下所示
由于没有同步,所以运行结果如下所示


t1, 你是第2个使用timer的线程


t2, 你是第2个使用timer的线程


也就是说当线程一运行到num++的时候被打线程2打断了,由于java中递增和递减操作均不是原子操作,所以本程序中即使没有调用sleep,也会出现这种被打断的情况

下面看看同步的效果

[java]
public void add(String name) {
synchronized (this) {//同步
num++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println(name + ", 你是第" + num + "个使用timer的线程");
}
}
public void add(String name) {
synchronized (this) {//同步 www.2cto.com
num++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println(name + ", 你是第" + num + "个使用timer的线程");
}
}

这样运行结果就会出是正确的

t1, 你是第1个使用timer的线程


t2, 你是第2个使用timer的线程

但是,下面为了说明问题把TestSync里面的run方法改成如下所示

[java]
public void run() {
/
time.add(Thread.currentThread().getName());
try {
Thread.sleep(1000);//为了显示结果,让其睡眠一秒
} catch (InterruptedException ex) {
Logger.getLogger(TestSync.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(Thread.currentThread().getName() + "----");
}
public void run() {
//
time.add(Thread.currentThread().getName());
try {
Thread.sleep(1000);//为了显示结果,让其睡眠一秒
} catch (InterruptedException ex) {
Logger.getLogger(TestSync.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(Thread.currentThread().getName() + "----");
}

那么在此运行就是


t1, 你是第