java互斥和同步_java同步和互斥【用具体程序说明】

所有对象都自动含有单一的锁,也就是所有对象都有且只有唯一的锁,所以当某个任务(线程)访问一个类A中含有sycnhronized的方法是,那么在这个线程从该方法返回之前(也就是该方法在当前线程执行完之前),类A中的其他被该关键字标记的方法在其他的线程中都会被阻塞。

通俗点说就是,当调用A的含有synchronized的方法是,A会被枷锁,此时A中其他含有synchronized方法只有等到前一个方法调用完毕释放了锁才能被调用

具体说明见另一篇博客<

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

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的线程");

}

}

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

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

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

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

下面看看同步的效果

public void add(String name) {

synchronized (this) {//同步

num++;

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

}

System.out.println(name + ", 你是第" + num + "个使用timer的线程");

}

}

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

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

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

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

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, 你是第1个使用timer的线程

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

t1--------

t2--------

而不是你所想象的

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

t1----

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

t2----

原因就是在线程t1在睡眠的时候,线程t2切换进来,执行了一次,怎样得到正确的结果呢,下面把TestSync里面的run方法做如下改进就可以得到上面预期的结果

public void run() {

synchronized(time){

time.add(Thread.currentThread().getName());

try {

Thread.sleep(3000);

} catch (InterruptedException ex) {

Logger.getLogger(TestSync.class.getName()).log(Level.SEVERE, null, ex);

}

System.out.println(Thread.currentThread().getName() + "----");

}

}

因为t1先获得time的锁,所以在执行完run里面的同步块之前,即使sleep(),t2也不会执行,因为t2没有获得time的锁,且sleep()操作也不释放锁(这也是和wait的巨大区别)

附录:TestSync.java全部代码

package com.bankht.synchronize;

import java.util.logging.Level;

import java.util.logging.Logger;

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());

//  }

//   public void run() {

//       timer.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() {

synchronized(timer){

timer.add(Thread.currentThread().getName());

try {

Thread.sleep(3000);

} catch (InterruptedException ex) {

Logger.getLogger(TestSync.class.getName()).log(Level.SEVERE, null, ex);

}

System.out.println(Thread.currentThread().getName() + "----");

}

}

}

class Timer {

private static int num = 0;

//  public void add(String name) {

//

//      num++;

//      try {

//          Thread.sleep(1000);

//      } catch (InterruptedException e) {

//      }

//      System.out.println(name + ", 你是第" + num + "个使用timer的线程");

//

//  }

public void add(String name) {

synchronized (this) {// 同步

num++;

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

}

System.out.println(name + ", 你是第" + num + "个使用timer的线程");

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值