//原子性
public class VolatileDemo {
public static void main(String[] args) {
Mydata mydata = new Mydata();
new Thread(()->{
System.out.println(Thread.currentThread().getName() + "1");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
mydata.addT060();
System.out.println(Thread.currentThread().getName() + "update");
},"A").start();
while (mydata.num == 0){
}
System.out.println(Thread.currentThread().getName() + "2");
}
}
class Mydata{
volatile int num = 0;
public void addT060(){
this.num = 60;
}
}
//A1
//Aupdate
//线程一直运行
验证不能保证原子性
在putfield时,其他线程挂起,没有及时得到主内存的值改变消息
public class VolatileDemo {
private static ExecutorService executorService = Executors.newFixedThreadPool(20);
// 验证可见性
/*public static void main(String[] args) {
Mydata mydata = new Mydata();
new Thread(()->{
System.out.println(Thread.currentThread().getName() + "1");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
mydata.addT060();
System.out.println(Thread.currentThread().getName() + "update");
},"A").start();
while (mydata.num == 0){
}
System.out.println(Thread.currentThread().getName() + "2");
}*/
// 验证不能保证原子性(已经volatile修饰了)
public static void main(String[] args) {
Mydata mydata = new Mydata();
for (int i = 1; i <= 20; i++) {
new Thread(()->{
for (int j = 1; j <= 1000; j++) {
mydata.addPlus();
mydata.addPlusByAtomic();
}
}, String.valueOf(i)).start();
}
//暂停一会儿线程
//需要等待上面20个线程全部计算完成后,由main方法取出结果值
/* try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
//必定有2个线程 main和gc
while (Thread.activeCount() > 2){
//礼让线程,本线程不执行
Thread.yield();
}
System.out.println("finally print:" + mydata.num);
System.out.println("finally print by atomic:" + mydata.atomicInteger);
}
}
class Mydata{
volatile int num = 0;
public void addT060(){
this.num = 60;
}
//
public void addPlus(){
num++;
}
AtomicInteger atomicInteger = new AtomicInteger(0);
public void addPlusByAtomic(){
atomicInteger.getAndIncrement();
}
}
有序性
指令重排序
不能,存在数据的依赖性
存在一种情况,那就是先执行的
flag=true
a=1
还未执行,这是其他线程抢占到资源,执行method2
,最后结果为5 ,此时加入volatile关键字,禁止指令重排序即可解决问题
volatile的使用场景
CAS
如果线程的期望值和物理内存的真实值一样,则修改更新值,如果不一样,本次修改失败,重新获取主物理内存的值。
this:当前这个对象 valueoffset:内存偏移量(这个对象的地址值),
CAS缺点
搞清楚变量的作用域
同步方法访问里层的同步方法,用的是同一把锁
case one
case two
lock可以重复,但是需要配对,有申请就需要就释放
自旋锁
自旋锁:优点:不会阻塞,缺点,一直循环,系统变慢
独占锁(写锁)/共享锁(读锁)/互斥锁
public class Lock8Demo1 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
try {
phone.sendEmail();
} catch (Exception e) {
e.printStackTrace();
}
},"A").start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
try {
phone.sendMsg();
} catch (Exception e) {
e.printStackTrace();
}
},"B").start();
}
}
class Phone{
public synchronized void sendMsg() throws Exception{
TimeUnit.SECONDS.sleep(4);
System.out.println("sendMsg**************");
}
public synchronized void sendEmail() throws Exception{
System.out.println("sendEmail**************");
}
public void sayHello(){
System.out.println("sayHello**************");
}
生产者消费者
/**
* @author:
* @description:
* @create: 2019-11-03 12:03
* 使用synchronized系列完成
* 题:现在两个线程,现在操作初始值为零的变量,实现一个线程对该变量加一,一个线程对该变量减一,操作10轮
* 多线程交互关键:
* 1.高内聚低耦合前提下,线程操作资源类
* 2.判断,干活,通知
* 3.防止虚假唤醒(多线程交互种判断必须要用while,不能用if)
*/
public class ProdecureConsumerDemo {
public static void main(String[] args) {
//资源类
Aircondition ad = new Aircondition();
new Thread(()->{
for (int i = 0; i < 10; i++) {
ad.increment();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
ad.decrement();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
ad.increment();
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
ad.decrement();
}
},"D").start();
}
}
class Aircondition{
private int num = 0;
public synchronized void increment(){
// 判断
// if (num != 0){
while (num != 0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 干活
num++;
System.out.println(Thread.currentThread().getName() + ":" + num);
// 通知
this.notifyAll();
}
public synchronized void decrement(){
//if (num == 0){
while (num == 0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 干活
num--;
System.out.println(Thread.currentThread().getName() + ":" + num);
// 通知
this.notifyAll();
}
}
public class CountDownLatchDemo {
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 0; i < 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName()+ "离开了教室");
countDownLatch.countDown();
}, String.valueOf(i)).start();
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "最后一个人离开了教室");
}
}
CyclicBarrier
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
System.out.println("第七次了,我执行了");
});
for (int i = 0; i < 7; i++) {
final int temp = i;
new Thread( ()->{
System.out.println(temp);
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
Semaphore
public class SemaphoreDemo {
public static void main(String[] args) {
// 模拟资源类,当前有3个车位
Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 6; i++) {
new Thread(()->{
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "\t抢到了车位");
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + "\t离开了车位");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}, String.valueOf(i)).start();
}
}
}
读写锁
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCache myCache = new MyCache();
for (int i = 0; i < 5; i++) {
// lambda中不允许变量
final int temp = i;
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
myCache.put(temp + "", temp + "");
} ,String.valueOf(i)).start();
}
for (int i = 0; i < 5; i++) {
// lambda中不允许变量
final int temp = i;
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
myCache.get(temp + "");
} ,String.valueOf(i)).start();
}
}
}
class MyCache{
private Map<String, Object> map = new HashMap<>();
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public void put(String key, Object value){
readWriteLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " \t 写入数据" + key);
map.put(key, value);
System.out.println(Thread.currentThread().getName() + " \t 写入完成");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.writeLock().unlock();
}
}
public void get(String key){
readWriteLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " \t 开始读取数据" );
Object o = map.get(key);
System.out.println(Thread.currentThread().getName() + " \t 读取完成" + key +":"+ o );
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.readLock().unlock();
}
}
队列