场景说明
假设有 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();
}
}
程序运行的时序图: