1.同步方法

即有synchronized关键字修饰的方法。
由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,
内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。
代码如:
public synchronized void save(){}
注: synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类
public class Bank {private int count =0;//账户余额//存钱public  synchronized void addMoney(int money){count +=money;System.out.println(System.currentTimeMillis()+"存进:"+money);}//取钱public  synchronized void subMoney(int money){if(count-money < 0){System.out.println("余额不足");return;}count -=money;System.out.println(+System.currentTimeMillis()+"取出:"+money);}//查询public void lookMoney(){System.out.println("账户余额:"+count);}
}

2.同步代码块

即有synchronized关键字修饰的语句块。
被该关键字修饰的语句块会自动被加上内置锁,从而实现同步
代码如:
synchronized(object){
}注:同步是一种高开销的操作,因此应该尽量减少同步的内容。
通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。
public class Bank {private int count =0;//账户余额//存钱public  void addMoney(int money){synchronized (this) {count +=money;}System.out.println(System.currentTimeMillis()+"存进:"+money);}//取钱public   void subMoney(int money){synchronized (this) {if(count-money < 0){System.out.println("余额不足");return;}count -=money;}System.out.println(+System.currentTimeMillis()+"取出:"+money);}//查询public void lookMoney(){System.out.println("账户余额:"+count);}
}

这样也实现了线程同步,运行效率上来说也比方法同步效率高,同步是一种高开销的操作,因此应该尽量减少同步的内容。通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。。

3.使用特殊域变量(volatile)实现线程同步

a.volatile关键字为域变量的访问提供了一种免锁机制,
b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新,
c.因此每次使用该域就要重新计算,而不是使用寄存器中的值
d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量

Bank.java代码如下:

package com.thread.demo;/*** Created by HJS on 2017/8/12.*/
public class Bank {private volatile int count =0;//账户余额//存钱public  void addMoney(int money){synchronized (this) {count +=money;}System.out.println(System.currentTimeMillis()+"存进:"+money);}//取钱public   void subMoney(int money){synchronized (this) {if(count-money < 0){System.out.println("余额不足");return;}count -=money;}System.out.println(+System.currentTimeMillis()+"取出:"+money);}//查询public void lookMoney(){System.out.println("账户余额:"+count);}
}

此时,顺序又乱了,说明同步又出现了问题,因为volatile不能保证原子操作导致的,因此volatile不能代替synchronized。此外volatile会组织编译器对代码优化,因此能不使用它就不适用它吧。它的原理是每次要线程要访问volatile修饰的变量时都是从内存中读取,而不是存缓存当中读取,因此每个线程访问到的变量值都是一样的。这样就保证了同步。

4.使用重入锁实现线程同步
在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。ReentrantLock类是可重入、互斥、实现了Lock接口的锁, 它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力。
ReenreantLock类的常用方法有:
ReentrantLock() : 创建一个ReentrantLock实例
lock() : 获得锁
unlock() : 释放锁
注:ReentrantLock()还有一个可以创建公平锁的构造方法,但由于能大幅度降低程序运行效率,不推荐使用
Bank.java代码修改如下:

public class Bank {private  int count = 0;// 账户余额//需要声明这个锁private Lock lock = new ReentrantLock();// 存钱public void addMoney(int money) {lock.lock();//上锁try{count += money;System.out.println(System.currentTimeMillis() + "存进:" + money);}finally{lock.unlock();//解锁}}// 取钱public void subMoney(int money) {lock.lock();try{if (count - money < 0) {System.out.println("余额不足");return;}count -= money;System.out.println(+System.currentTimeMillis() + "取出:" + money);}finally{lock.unlock();}}// 查询public void lookMoney() {System.out.println("账户余额:" + count);}
}

注:关于Lock对象和synchronized关键字的选择:

    a.最好两个都不用,使用一种java.util.concurrent包提供的机制, 能够帮助用户处理所有与锁相关的代码。 b.如果synchronized关键字能满足用户的需求,就用synchronized,因为它能简化代码 c.如果需要更高级的功能,就用ReentrantLock类,此时要注意及时释放锁,否则会出现死锁,通常在finally代码释放锁 。

java实现同步的几种方式(总结)相关推荐

  1. Java线程同步的几种方式

    Java线程同步的几种方式 1.使用synchronized关键字  它的工作是对同步的代码加锁,使得每一次只能有一个线程进入同步块,从而保证线程间的安全性.  synchronized关键字的用法: ...

  2. java实现同步的两种方式

    同步是多线程中的重要概念.同步的使用可以保证在多线程运行的环境中,程序不会产生设计之外的错误结果.同步的实现方式有两种,同步方法和同步块,这两种方式都要用到synchronized关键字. 给一个方法 ...

  3. Java字符串连接的几种方式

    Java字符串连接的几种方式 字符串表现的几种方式 StringBuffer和StringBuilder及String的继承关系 字符串的连接 1.String的连接方法 可以看出连接方式是新建了一个 ...

  4. java多线程同步的四种方法_java中实现多线程的两种方法

    java多线程有几种实现方法,都是什么?同步有几种实java中多线程的实现方法有两种:1.直接继承thread类:2.实现runnable接口:同步的实现方法有五种:1.同步方法:2.同步代码块:3. ...

  5. 最优雅的Java字符串拼接是哪种方式?

    title shortTitle category tag description head 最优雅的Java字符串拼接是哪种方式? Java字符串拼接 Java核心 数组&字符串 Java程 ...

  6. java怎样输入五个数字打一成语,Java的线程安全四种方式五个等级[1]

    Java的线程安全四种方式五个等级[1]以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 四种方式 sychronized ...

  7. 12月18日云栖精选夜读 | Java 中创建对象的 5 种方式!...

    作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如Spring去创建对象.然而这里有很多创建对象的方法,我们会在这篇文章中学到. Java中有5种创建对象的方式,下面给出它们的 ...

  8. Java中创建对象的几种方式

    Java中创建对象的几种方式 1.使用new创建对象,在堆上创建. 2.克隆 3.反序列化 4.反射创建对象 5.NIO中可以使用本地方法直接分配堆外内存. 转载于:https://www.cnblo ...

  9. Java中创建对象的四种方式

    为什么80%的码农都做不了架构师?>>>    Java中创建对象的四种方式 (1) 用new语句创建对象,这是最常见的创建对象的方法.    (2) 运用反射手段,调用java.l ...

  10. Linux C++多线程同步的四种方式

    目录 一.互斥锁 二.条件变量 三.读写锁 原文链接:Linux C++多线程同步的四种方式(非常详细)_Y先森0.0-CSDN博客 背景问题:在特定的应用场景下,多线程不进行同步会造成什么问题? 通 ...

最新文章

  1. 真牛X!这款通用数据库连接工具DBeaver!可以连接和操作市面所有的数据库!...
  2. eclipse 中文件引用报错不能编译,但引用文件确实存在
  3. 简单易学的机器学习算法——神经网络之BP神经网络
  4. 接雨水—leetcode42
  5. Oracle学习(1)——BLOCK
  6. oem是代工还是贴牌_食用油OEM贴牌代工业务要注意哪些问题?
  7. 官方回应 ,清华大学对于造假的处理结果来了:一作撤销博士学位,导师停止招生资格及提前退休...
  8. mysql5.7延迟_[MySQL] 号称永久解决了复制延迟问题的并行复制,MySQL5.7-阿里云开发者社区...
  9. 手写Maven的archetype项目脚手架
  10. windows 2003下配置IIS6为iis5方式的隔离模式运行
  11. ASP.NET----web用户控件
  12. 计算几何——判断点是否在多边形内
  13. 前端图片合成技术_让前端也能快速地合成图片!
  14. 蓝牙共享PC宽带上网
  15. vue之使用vue-cli搭建SPA项目
  16. Ubuntu14.04 使用本地摄像头跑ORB SLAM2
  17. 如何查已经欠费的联通手机号码
  18. CAD高版本转低版本的方法有哪些?你一定用的到哦
  19. 葡,西两国发展史(大航海时代)启示
  20. 直男七夕送礼指南,这四款总有你女票的菜

热门文章

  1. 编程英语单词1.编程常用英语词汇大全
  2. 录屏软件推荐:bilibili哔哩哔哩直播姬录屏软件下载使用指南
  3. 行程匹配的算法python_节约里程算法的python实现
  4. 【标书应用场景】畅写Office为电子招投标提速赋能,助力项目招投标业务数字化转型
  5. 【CodeForces 1260D --- A Game with Traps】二分
  6. 在Ubuntu 20.04(Linux Mint 各衍生版)上安装使用国金证券 通达信 客户端软件。
  7. js导出excel(超简单)
  8. python井字棋_用python井字棋
  9. 基于深度学习的SLAM综述:迈向空间机器智能时代
  10. JavaWeb教程———Ajax