[笔记][Java7并发编程实战手册]2.2使用syncronized实现同步方法
来源:互联网 发布:mac删除windows后内存 编辑:程序博客网 时间:2024/06/05 09:19
[笔记][Java7并发编程实战手册]系列目录
学习多线程之前,我觉得很有必要去学习下
[笔记][思维导图]读深入理解JAVA内存模型整理的思维导图
基础知识
- 锁除了让临界区互斥执行外,
还可以让释放锁的线程向获取同一个锁的线程发送消息 - 当线程获取锁时,JMM会把该线程对应的本地内存置为无效。
从而使得监视器保护的临界区代码必须要从主内存中去读取共享变量。 - 当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。
- 加锁使用的是同一个锁的话,使用syncronized的静态方法和普通方法需要注意的是:静态方法:同时只能被一个线程访问,但是可以访问其他被syncronized修饰过的普通方法,所以:如果存在静态和非静态方法中都修改了同一个数据,那么就会出现并发问题
针对基础知识中的第4点验证
其他三点,请看java内存模型
例子:
public class SyncStatic { public static void main(String[] args) throws InterruptedException {public class SyncStatic { public static void main(String[] args) throws InterruptedException { final A a = new A(); Thread t1 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i++) { a.addStatic(); try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } } } }); t1.start(); Thread t2 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i++) { a.sub(); try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } } } }); t2.start(); t1.join(); t2.join(); System.out.println(a.num); }}class A{ public static int num = 0; public static synchronized void addStatic(){ ++num; System.out.println("addStatic:" + num); } /** * 想看到正确的结果,请把这里的static注释放开 */ public /*static*/ synchronized void sub(){ --num; System.out.println("sub:" + num); }}
某一次运行结果:
addStatic:0sub:0sub:0addStatic:1addStatic:1sub:0sub:-1addStatic:0sub:-1addStatic:0addStatic:1sub:1addStatic:1sub:1sub:0addStatic:1sub:1addStatic:1addStatic:2sub:22
说明:
一个A类。两个线程:一个线程相加10次,一个线程相减10次,最后的结果肯定是不变的。但是这里实现正面变化了。所以说:要注意被syncronized修饰过的静态方法
充钱取钱的列子
** * Created by zhuqiang on 2015/8/5 0005. * 模拟账户 */public class Account { private String userName; //用户 private double money; //余额 public synchronized void add(double money){ this.money = this.money + money; System.out.println(this.getUserName() + ",+100:余额:" + this.getMoney()); } public synchronized void subtract(double money){ this.money = this.money - money; System.out.println(this.getUserName() + ",-100:余额:" + this.getMoney()); } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public double getMoney() { return money; } public void setMoney(double money) { this.money = money; }}/** * Created by zhuqiang on 2015/8/5 0005. * atm 机器,往里面不断的充值 */public class AtmAdd implements Runnable { private Account account; public AtmAdd(Account account){ this.account = account; } @Override public void run() { for (int i = 1;i <=100;i++){ account.add(100); } }}/** * Created by zhuqiang on 2015/8/5 0005. * atm 机器,往里面不断的扣钱 */public class AtmSub implements Runnable { private Account account; public AtmSub(Account account){ this.account = account; } @Override public void run() { for (int i = 1;i <=100;i++){ account.subtract(100); } }}/** * Created by zhuqiang on 2015/8/5 0005. */public class Client { public static void main(String[] args) throws Exception { Account account = new Account(); account.setMoney(0); account.setUserName("小明"); Thread add = new Thread(new AtmAdd(account)); add.start(); Thread sub = new Thread(new AtmSub(account)); sub.start(); add.join(); //等待该线程终止,主线程才执行 sub.join(); System.out.println(account.getMoney()); }}
说明:
运行结果就不贴出了;
该示例有2个线程,一个线程不断的往账户中冲钱,一个线程不断的往账户中扣钱。正确同步的结果是最后账户中的钱是不变的。因为执行的次数都一样
使用非依赖属性实现同步
一般在方法上加syncronized,是使用当前对象的锁,比如
syncronized(this){ ...}
那么可以使用不同的对象来替代this,并发操作不同的共享数据。而不用全部都等待this锁。
比如:下面这种情况,a,b之间没有什么关系。但是又要不相关的线程也要排队等待。就可以使用不同的对象来替代this
int a ; int bsyncronized(this){ b++ ...}syncronized(this){ a++ ...}
0 0
- [笔记][Java7并发编程实战手册]2.2使用syncronized实现同步方法
- [笔记][Java7并发编程实战手册]2.5使用Lock实现同步一
- [笔记][Java7并发编程实战手册]2.5使用Lock实现同步二
- [笔记][Java7并发编程实战手册]2.4在同步代码中使用条件-生产者与消费者
- [笔记][Java7并发编程实战手册]第三章-线程同步辅助类-3.1概要
- [笔记][Java7并发编程实战手册]3.5 在集合点的同步CyclicBarrier循环barrier
- [笔记][Java7并发编程实战手册]6.并发集合
- [笔记][Java7并发编程实战手册]7. 定制并发类
- [笔记][Java7并发编程实战手册]系列目录
- JAVA7并发编程手册笔记
- [笔记][Java7并发编程实战手册]3.2 资源的并发访问控制Semaphore信号量
- [笔记][Java7并发编程实战手册]3.3 资源的多副本并发访问控制Semaphore
- [笔记][Java7并发编程实战手册]3.6 并发阶段任务的运行phaser
- [笔记][Java7并发编程实战手册]3.7 并发阶段任务中的阶段切换phaser
- [笔记][Java7并发编程实战手册]3.8 并发任务间的数据交换Exchanger
- [笔记][Java7并发编程实战手册]系列第四章 4.1 简介
- [笔记][Java7并发编程实战手册]4.2 创建线程执行器newCachedThreadPool无界线程池
- [笔记][Java7并发编程实战手册]4.3 创建固定的线程执行器newFixedThreadPool线程池
- 聊聊我的高效编程之路
- UBI error: ubi_io_write: error -5 while writing 512 bytes to PEB 60:512, wri
- 1039. 到底买不买(20)
- Logcat日志不打印(可能是手机出厂做了限制)
- GCD介绍(三):Dispatch Sources
- [笔记][Java7并发编程实战手册]2.2使用syncronized实现同步方法
- org.springframework.validation.BindException
- LeetCode Everyday -- 83
- 【hibernate mapping 详解】….hbm.xml配置
- adb停止工作解决
- Constructor call must be the first statement in a constructor
- 在开发板上挂载NFS
- list,map,set,array的特点和相互转换
- 各种开源框架集锦