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

来源:互联网 发布:淘宝女人频道 编辑:程序博客网 时间:2024/06/05 06:37

场景说明

假设有 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
  • 类中的 static 类型的对象
  • 或者在 main 方法中 new 一个对象

第一种代码的实现

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

程序运行的时序图:

第二种实现的时序图