博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
转:关于JAVA多线程同步
阅读量:4324 次
发布时间:2019-06-06

本文共 4167 字,大约阅读时间需要 13 分钟。

转:http://lanvis.blog.163.com/blog/static/26982162009798422547/

因为需要,最近关注了一下JAVA多线程同步问题。JAVA多线程同步主要依赖于若干方法和关键字。将心得记录如下:


1  wait方法:
        该方法属于Object的方法,wait方法的作用是使得当前调用wait方法所在部分(代码块)的线程停止执行,并释放当前获得的调用wait所在的代码块的锁,并在其他线程调用notify或者notifyAll方法时恢复到竞争锁状态(一旦获得锁就恢复执行)。
        调用wait方法需要注意几点:
        第一点:wait被调用的时候必须在拥有锁(即synchronized修饰的)的代码块中。
        第二点:恢复执行后,从wait的下一条语句开始执行,因而wait方法总是应当在while循环中调用,以免出现恢复执行后继续执行的条件不满足却继续执行的情况。
        第三点:若wait方法参数中带时间,则除了notify和notifyAll被调用能激活处于wait状态(等待状态)的线程进入锁竞争外,在其他线程中interrupt它或者参数时间到了之后,该线程也将被激活到竞争状态。
        第四点:wait方法被调用的线程必须获得之前执行到wait时释放掉的锁重新获得才能够恢复执行。
2  notify方法和notifyAll方法:
        notify方法通知调用了wait方法,但是尚未激活的一个线程进入线程调度队列(即进入锁竞争),注意不是立即执行。并且具体是哪一个线程不能保证。另外一点就是被唤醒的这个线程一定是在等待wait所释放的锁。
        notifyAll方法则唤醒所有调用了wait方法,尚未激活的进程进入竞争队列。
3 synchronized关键字:
        第一点:synchronized用来标识一个普通方法时,表示一个线程要执行该方法,必须取得该方法所在的对象的锁。
        第二点:synchronized用来标识一个静态方法时,表示一个线程要执行该方法,必须获得该方法所在的类的类锁。
        第三点:synchronized修饰一个代码块。类似这样:synchronized(obj) { //code.... }。表示一个线程要执行该代码块,必须获得obj的锁。这样做的目的是减小锁的粒度,保证当不同块所需的锁不冲突时不用对整个对象加锁。利用零长度的byte数组对象做obj非常经济。
4 atomic action(原子操作):
        在JAVA中,以下两点操作是原子操作。但是c和c++中并不如此。
        第一点:对引用变量和除了long和double之外的原始数据类型变量进行读写。
        第二点:对所有声明为volatile的变量(包括long和double)的读写。
        另外:在java.util.concurrent和java.util.concurrent.atomic包中提供了一些不依赖于同步机制的线程安全的类和方法。

1 5 一个例子,该例子模仿多人存取同一个账户: 2 Account类: 3 package com.synchronize; 4  5 import java.util.HashMap; 6 import java.util.Iterator; 7  8 public class Account { 9     private static HashMap
m = new HashMap
();10 private static long times = 0;11 static {12 m.put("ren", 1000);13 }14 15 public synchronized void save(String name, int num) {16 long tempTime = times++;17 System.out.println("第 " + tempTime + " 次存储" + num + "之前" + name + "的余额为:" + m.get(name));18 m.put(name, m.get(name) + num);19 this.notify();20 System.out.println("第 " + tempTime + " 次存储" + num + "之后" + name + "的余额为:" + m.get(name));21 }22 23 public static int get(String name) {24 return m.get(name);25 }26 27 /**28 * 注意wait的用法,必须在loop中,必须在拥有锁的代码块中。 前者是当被notify的时候要重新进行条件判断,后者是为了释放锁。29 * 30 * @param name31 * @param num32 */33 public synchronized void load(String name, int num) {34 long tempTime = times++;35 System.out.println("第 " + tempTime + " 次提取" + num + "之前" + name + "的余额为:" + m.get(name));36 37 try {38 while (m.get(name) < num) {39 System.out.println("第 " + tempTime + " 次提取" + "余额" + m.get(name) + "不足,开始等待wait。");40 this.wait();41 System.out.println("第 " + tempTime + " 次提取操作被唤醒");42 }43 } catch (InterruptedException e) {44 // TODO Auto-generated catch block45 e.printStackTrace();46 }47 m.put(name, m.get(name) - num);48 System.out.println("第 " + tempTime + " 次提取" + num + "之后" + name + "的余额为:" + m.get(name));49 }50 }51 52 53 User类:54 package com.synchronize;55 56 /**57 * 这里注意runnable接口的线程是怎么实例化的。new Thread(new User())58 * 这里成功展示了多个用户存取同一个账户的多线程实例,通过多线程同步,保证了安全的执行。59 * @author abc60 * 61 */62 public class User implements Runnable {63 private static Account account = new Account();64 private final int id;65 66 User(int i){67 id=i;68 }69 70 public void run() {71 int tempMoney = 100;72 account.load("ren", tempMoney);73 try {74 Thread.sleep(3000);75 } catch (InterruptedException e) {76 // TODO Auto-generated catch block77 e.printStackTrace();78 }79 account.save("ren", 100);80 System.out.println("线程"+id+"完毕========================================================");81 }82 83 public static void main(String[] args) {84 for (int i = 0; i < 100; i++) {85 new Thread(new User(i)).start();86 }87 }88 }89 90 后续:请额外关注 ThreadLocal、JDK 5 中增加的 Lock 接口。91 参考资料:92 1 JDK Document93 2 http://java.sun.com/docs/books/tutorial/essential/concurrency/locksync.html94 3 http://java.sun.com/docs/books/tutorial/essential/concurrency/atomic.html

 

转载于:https://www.cnblogs.com/yaowukonga/p/3767559.html

你可能感兴趣的文章
css规范 - bem
查看>>
电梯调度程序的UI设计
查看>>
转自 zera php中extends和implements的区别
查看>>
Array.of使用实例
查看>>
【Luogu】P2498拯救小云公主(spfa)
查看>>
如何获取网站icon
查看>>
几种排序写法
查看>>
java 多线程的应用场景
查看>>
dell support
查看>>
[Hive - LanguageManual] Alter Table/Partition/Column
查看>>
可持久化数组
查看>>
去除IDEA报黄色/灰色的重复代码的下划波浪线
查看>>
Linux发送qq、网易邮件服务配置
查看>>
几道面试题
查看>>
【转】使用 WebGL 进行 3D 开发,第 1 部分: WebGL 简介
查看>>
js用正则表达式控制价格输入
查看>>
chromium浏览器开发系列第三篇:chromium源码目录结构
查看>>
java开发操作系统内核:由实模式进入保护模式之32位寻址
查看>>
第五讲:单例模式
查看>>
Python编程语言的起源
查看>>