多线程实现互斥访问对象的方法

场景说明

假设有 A、B 两个线程都去调用对象 α 的方法 method1(),并且要求 A、B 两个线程是互斥调用 method1 的。具体来说,假设 method1 中有 4 个命令,一旦 A 调用了 method1,在执行 method1 中有 4 个命令的时候,B 不会调用 method1 方法,反之,也一样。

利用 java的同步机制

在 JAVA 中的 Object 类型中,都是带有一个内存锁的,在有线程获取该内存锁后,其它线程无法访问该内存,从而实现JAVA中简单的同步、互斥操作。具体到代码中,涉及到三个关键字:

  • synchronize:这个关键字会实现对象的方法互斥的执行
  • notify:通知另外一个正在等待进程可以申请资源
  • wait:本线程主动释放资源
  • notify、wait 实现了线程间的通信

经常被锁的资源为:

  • 字节码:对象的 class,例如,A.class ,此锁为类锁,它是的上面上锁的,在整个 JVM 中,只有一个类,而且一个类只能上一个锁。
  • 类中的 static 类型的对象,同上。
  • 或者在 main 方法中 new 一个对象。此锁是对象锁,此锁是在对象的上面上锁的,在整个 JVM 中,可以有多个对象,所以对象锁比类锁,力度可以更细。

第一种实现

package wyf.org.concurrent.KeyWord;

public class Word implements Runnable {
	private String name ;
	private int count = 0 ;
	public Object o ;
	public Word(String name, Object o){
		this.name = name;
		this.o = o ;
	}
	
	public  void output() throws InterruptedException{
		
		synchronized(o){
			o.notify();//当程序走到这里,会先执行 notify 的操作,无论是 a 或者 b 都会得到 o 的锁并且执行下面的 5 行代码,最后 wait 主动让出 o 的锁
			System.out.println(name +  " 1, thread run ");
			Thread.sleep(1000);
			System.out.println(name +  " 2, thread run ");
			System.out.println(name +  " 3, thread run ");
			System.out.println(" ");
			o.wait();
		}
	}
	public static void main(String[] args) {
		
	/*
	 * 使用一个 object 来作为同步的的临界值,哪个线程得了 object 的锁就能,活得 synchronized 中代码的执行资源
	 * */
		Object o = new Object();
		Word a = new Word("A",o);
		Word b = new Word("B",o);
		new Thread(a).start();
		new Thread(b).start();
	}

	public void run() {
		while(true){
			try {
				this.output();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

下面是程序运行的时序图:

进程的时序图

第二种代码的实现

package wyf.org.concurrent.KeyWord;

public class SynchroniseWord implements Runnable{
	
	private String name = "";
	public SynchroniseWord(String name){
		this.name = name ;
	}
	public synchronized void Count() throws InterruptedException{
		System.out.println(name +  " 1, thread run ");
		Thread.sleep(1000);
		System.out.println(name +  " 2, thread run ");
		System.out.println(name +  " 3, thread run ");
		System.out.println(" ");
	}
	
	public void run() {
		while(true){
			try {
				this.Count();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) {
		SynchroniseWord sw = new SynchroniseWord("A");
		new Thread(sw).start();
		new Thread(sw).start();
	}
}

程序运行的时序图:

第二种实现的时序图

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值