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

场景说明

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

程序运行的时序图:

第二种实现的时序图

猜你喜欢

转载自blog.csdn.net/bluedraam_pp/article/details/78671148
今日推荐