0
点赞
收藏
分享

微信扫一扫

第14章 多线程(5) synchronized代码块与 volatile 用法


第14章 多线程(5) synchronized代码块与 volatile 用法_全局变量

第14章 多线程(5) synchronized代码块与 volatile 用法_加锁_02

 14.5.6 同步阻塞

Sychronized 除了可以用于使用同步方法外,也可以使用单独对象来作为代码段锁:synchronized(obj){//do something}

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Bank {
private final double[] accounts;
private Lock bankLock = new ReentrantLock();
public Bank(int n, double initialBalance){
accounts = new double[n];
for(int i = 0; i < n; i++){
accounts[i] = initialBalance;
}

}

public void transfer(int from, int to, double amount){
synchronized (accounts){
if(accounts[from] < amount) return;
System.out.print(Thread.currentThread());
accounts[from] -= amount;
System.out.printf(" %10.2f from %d to %d", amount, from, to);
accounts[to] += amount;
System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
}

}

private synchronized double getTotalBalance(){
double sum = 0;
for(double a: accounts){
sum += a;
}

return sum;
}

public int size(){
return accounts.length;
}
}

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

运行结果:

🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍

第14章 多线程(5) synchronized代码块与 volatile 用法_java_03

🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍

注意这里我直接用的同步对象作为锁,事实上更为常见的做法是,创建一个单独的全局对象作为锁处理 Object lock = new Object()

第14章 多线程(5) synchronized代码块与 volatile 用法_idea_04

 14.5.7 监视器概念

监视器:在不需要程序员考虑加锁的情况下,保证多线程的安全。

期望特性:

🎯 监视器只包含私有类

🎯 每个监视器只有一个锁

🎯 使用该锁对所有方法统一加锁,进入任意方法时加锁,调用完成时释放锁

🎯 该所可以有多个条件

导致监视器安全性降低的原因:

🎯 全局不强制要求 private

🎯 方法不要求 synchronized

🎯 内部锁客户可用

14.5.8 Volatile 全局变量

相对于 synchronized(obj){} 和 lock.lock()/lock.unlock, synchronized 一个方法的开销要大的多。面临的问题:

🎯 多处理器可能不同处理器在同一个位置读不一致

🎯 指令重排可以增强编译器的性能,但是与此同时带来的问题是,在修改前切换线程,可能导致值发生错误改变

Volatile 恰恰可以处理好这两个问题,

🎯 可见性:满足不同线程在同一时刻读取同一位置时值是最新的

🎯 有序性:通过增加读写屏障防止指令重排,保证所有指令按顺序执行

保证全局变量访问安全性的三个条件(满足一个即可):

🎯 final 类型(初始化后)

🎯 使用锁进行保护

🎯 使用volatile

相关内容:选择 《Java核心技术 卷1》查找相关笔记

评论🌹点赞👍收藏✨关注👀,是送给作者最好的礼物,愿我们共同学习,一起进步

公众号 钰娘娘知识汇总 

举报

相关推荐

0 条评论