解释:
When two or more threads need access to a shared resource, they need some way to ensure that the resource will be used by only one thread at a time.
The process by which this synchronization is achieved is called threadsynchronization.
The synchronized keyword in Java creates a block of code referred to as a critical section. Every Java object with a critical section of code gets a lock associated with the object. To enter a critical section, a thread needs to obtain the corresponding object'slock.
This is the general form of the synchronized statement:
synchronized(object) { // statements to be synchronized }
Here, object is a reference to the object being synchronized. A synchronized block ensures that a call to a method that is a member of object occurs only after the current thread has successfully entered object's monitor.
/**
* 线程间通讯:
* 其实就是多个线程在操作同一个资源
* 但是操作的动作不同
*/
wait, notify, notifyAll()
都是用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。
为什么这些操作线程的方法,要定义在object类中呢?
因为这些方法在操作同步中线程时,都必须要标识他们所操作线程持有的锁,
只有同一个锁上得被等待线程,可以被统一个锁上得notify唤醒。
不可以对不同锁中的线程进行唤醒。
也就是说,等待和唤醒必须是同一个锁。
而锁可以是任意对象,所以可以被任意对象调用的方法(wait, notify,notifyAll)定义在object类中
举例:Input类用于,传入内容,Output类用于传出内容,由于传输的数据是共享的,所以将这个传输的数据对象作为“锁”。
等待====》唤醒
为了能够输入线程,和输出线程一次只运行一个线程,于是:输入线程工作,输出等待,输入线程等待,输出线程工作。
由于此例中进加入了两个线程,所以使用notify来唤醒wait状态下的线程。
notify 只唤醒在线程池中最上面的那个线程
notify 唤醒线程池中所有的线程
public class Input implements Runnable {
private Res r;
public Input(Res r) {
super();
this.r = r;
}
@Override
public void run() {
int x = 0;
while (true) {
synchronized (r) {
if (r.flag)
try {
r.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (x == 0) {
r.name = "LI";
r.sex = "femal";
} else {
r.name = "李雷";
r.sex = "男";
}
x = (x + 1) % 2;
r.flag = true;
r.notify();
}
}
}
}
public class Output implements Runnable {
private Res r;
public Output(Res r) {
super();
this.r = r;
}
@Override
public void run() {
while (true) {
synchronized (r) {
if (!r.flag)
try {
r.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(r.name + "," + r.sex);
r.flag = false;
r.notify();
}
}
}
}
public class Res {
String name;
String sex;
boolean flag = false;
}
public class InputOutputDemo {
public static void main(String[] args) {
Res r = new Res();
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}
public class Res {
private String name;
private String sex;
private boolean flag = false;
public synchronized void set(String name, String sex) {
if (flag)
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
this.name = name;
this.sex = sex;
flag = true;
this.notify();
}
public synchronized void out() {
if (!flag)
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(name + "..." + sex);
flag = false;
this.notify();
}
}
public class Input implements Runnable {
private Res r;
public Input(Res r) {
super();
this.r = r;
}
@Override
public void run() {
int x = 0;
while (true) {
if (x == 0)
r.set("Li", "female");
else
r.set("李雷", "男");
x = (x + 1) % 2;
}
}
}
public class Output implements Runnable {
private Res r;
public Output(Res r) {
super();
this.r = r;
}
@Override
public void run() {
while (true) {
r.out();
}
}
}
public class InputOutputDemo {
public static void main(String[] args) {
Res r = new Res();
new Thread(new Input(r)).start();
new Thread(new Output(r)).start();
}
}