对上次多线程编程步骤补充(中部):
创建资源类,在资源类中创建属性和操作方法
在资源类里面操作
判断
干活
通知
创建多个线程,调用资源类的操作方法
线程通信的实现例子:
两个线程,实现对一个初始变量为0进行操作,一个线程对其+1,一个线程对其-1,使得变量结果不改变
使用Synchronized实现的线程通信:
package com.JUC;
/**
-
创建资源类
*/
class Share{
//初始值
private int number = 0;//创建方法
public synchronized void incr() throws InterruptedException {
//判断 干活 通知
if(number != 0){
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+"::"+number);
//通知其他线程
this.notifyAll();
//System.out.println(this.getClass());
}
public synchronized void decr() throws InterruptedException {
if(number != 1){
this.wait();
}
number–;
System.out.println(Thread.currentThread().getName()+"::"+number);
//唤醒其他的线程,这里的this指代在方法中指调用该方法的对象
this.notifyAll();
}
}
public class ThreadSignaling {
public static void main(String[] args) throws InterruptedException {
Share share = new Share();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.incr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"AAA").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
share.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"BBB").start();
}
}
volatile和synchronized关键字
volatile:即可见性,当修改一个变量的时候,如果该变量是通过volatile修饰的,那么其他所有的线程都会感知到该变量的变化情况。
如果不使用该关键字的话:
可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
举个简单的例子,看下面这段代码:
//线程1执行的代码
int i = 0;
i = 10;
//线程2执行的代码
j = i;
假若执行线程1的是CPU1,执行线程2的是CPU2。由上面的分析可知,当线程1执行 i =10这句时,会先把i的初始值加载到CPU1的高速缓存中,然后赋值为10,那么在CPU1的高速缓存当中i的值变为10了,却没有立即写入到主存当中。
此时线程2执行 j = i,它会先去主存读取i的值并加载到CPU2的缓存当中,注意此时内存当中i的值还是0,那么就会使得j的值为0,而不是10.
这就是可见性问题,线程1对变量i修改了之后,线程2没有立即看到线程1修改的值
亚马逊测评 www.yisuping.cn