synchronize


synchronized是Java中的关键字,是一种常用的线程同步锁。

用法

注意:在理解synchronized时,要知道一个核心点,synchronized锁定的不是代码,而是对象。使用synchronized时,其会申请对象的堆内存,进行锁定。

写法一

    Object o = new Object(); // 锁对象
public void test01(){
//任何线程要执行以下的代码,必须先拿到锁
synchronized (o){
// doSomething...
}
}

写法二

上述写法是创建一个锁对象,其实可以自身作为锁对象。

    public void test02(){
synchronized (this){
// doSomething...
}
}

写法三

同写法二。

    public synchronized void test03(){
// doSomething...
}

写法四

锁定静态方法。静态方法是属于类方法,没有对象。

    public synchronized static void test04(){
}

写法五

同写法四

    public static void test04(){
synchronized (SynchronizeTest.class){
}
}

测试线程安全问题

演示代码:

public class RunnableDemo implements Runnable {

    private int count = 10;

    @Override
public /*synchronized*/ void run() {
count--;
System.out.println(Thread.currentThread().getName() + "count=" + count);
} public static void main(String[] args) {
RunnableDemo t = new RunnableDemo();
for (int i = 0; i < 8; i++) {
new Thread(t, "结果是:" + i).start();
}
}
}

结果是:

结果是:1count=9
结果是:0count=8
结果是:2count=7
结果是:3count=6
结果是:5count=5
结果是:4count=4
结果是:6count=3
结果是:7count=2

加入synchronized:

结果是:0count=9
结果是:1count=8
结果是:2count=7
结果是:3count=6
结果是:4count=5
结果是:5count=4
结果是:6count=3
结果是:7count=2

可以看到输出顺序是不一样的.

注意事项

在实际业务场景中,往往将读方法不加锁,写的方法加锁,这样会导致一个问题,也就是读的数据是写之前的数据,导致脏读问题。解决方案就是,在读方法上也加锁

  1. 加锁方法不影响不加锁方法的执行;

  2. 加锁方法访问另外一个加锁方法,一个线程拥有某个对象的锁,再次申请的时候可以再次得到这把锁(相当于锁上了两把同样的锁);子类的同步方法调用父类的同步方法也可以;

  3. synchronized 遇到异常,锁会被释放。如果不想该锁被释放,就直接catch;

  4. 不要以字符串常量作为锁对象。

public class StringAsSynchObject {
private String stra = "hello";
private String strb = "hello";
void test1(){
synchronized (stra){
}
}
void test2(){
synchronized (strb){
}
}
}

在上述代码中,因为stra和strb 锁的是同一个对象,如果用到了同一个类库,在该类库中的代码锁定了字符串"hello",我们读不到源码,而在业务代码中也锁定了同样的字符串,这就有可能会造成非常诡异的死锁阻塞。因为程序和类库不经意用了同一把锁。(这种情况一般没办法调试)。所以通常不要字符串作为锁定对象。

  1. synchronize 锁定的粒度越小(即锁定的业务代码越少),效率越高。

  2. synchronize 锁释放的情况:

    1)线程执行完毕;

    2)线程发生异常;

    3)线程进入休眠状态。

  3. synchronize 是互斥锁,可重入锁。

  4. wait()和notify()/notifyAll() 与 synchronize同时出现。

并发编程(叁):synchronize的更多相关文章

  1. 并发编程(一):从头到脚解读synchronized

    一.目录 1.多线程启动方式 2.synchronized的基本用法 3.深度解析synchronized 4.同步方法与非同步方法是否能同时调用? 5.同步锁是否可重入(可重入锁)? 6.异常是否会 ...

  2. Java并发编程深入学习

    上周的面试中,被问及了几个并发开发的问题,自己回答的都不是很系统和全面,可以说是"头皮发麻",哈哈.因此果断购入<Java并发编程的艺术>一书,该书内容主要是对ifev ...

  3. 转: 【Java并发编程】之二十:并发新特性—Lock锁和条件变量(含代码)

    简单使用Lock锁 Java5中引入了新的锁机制--Java.util.concurrent.locks中的显式的互斥锁:Lock接口,它提供了比synchronized更加广泛的锁定操作.Lock接 ...

  4. Java 并发编程:volatile的使用及其原理

    Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ...

  5. Python3 与 C# 并发编程之~ 进程篇

      上次说了很多Linux下进程相关知识,这边不再复述,下面来说说Python的并发编程,如有错误欢迎提出- 如果遇到听不懂的可以看上一次的文章:https://www.cnblogs.com/dot ...

  6. Python3 与 C# 并发编程之~ 协程篇

      3.协程篇¶ 去年微信公众号就陆陆续续发布了,我一直以为博客也汇总同步了,这几天有朋友说一直没找到,遂发现,的确是漏了,所以补上一篇 在线预览:https://github.lesschina.c ...

  7. Android并发编程 开篇

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  8. 【Java并发编程】11、volatile的使用及其原理

    一.volatile的作用 在<Java并发编程:核心理论>一文中,我们已经提到过可见性.有序性及原子性问题,通常情况下我们可以通过Synchronized关键字来解决这些个问题,不过如果 ...

  9. Java并发编程快速学习

    上周的面试中,被问及了几个关于Java并发编程的问题,自己回答的都不是很系统和全面,可以说是"头皮发麻",哈哈.因此果断购入<Java并发编程的艺术>一书,学习后的体会 ...

  10. 那些年读过的书《Java并发编程的艺术》一、并发编程的挑战和并发机制的底层实现原理

    一.并发编程的挑战 1.上下文切换 (1)上下文切换的问题 在处理器上提供了强大的并行性就使得程序的并发成为了可能.处理器通过给不同的线程分配不同的时间片以实现线程执行的自动调度和切换,实现了程序并行 ...

随机推荐

  1. 如何系统地学习Excel?

    人在江湖,生不由己.人在职场,Excel必备. 为了帮助更多人快速掌握职场必备技能Excel,我写了一个免费的教程<职场Excel>,能帮助你解决99%职场中遇到的问题. 对,你没看错,是 ...

  2. Oracle Dataguard故障转移(failover)操作

    注意:故障转移会破坏DG的主从关系,使其变为互不相关的2个数据库,谨慎使用. (一)故障转移操作流程图 (二)故障转移操作流程 备注:以下操作步骤与上面流程图步骤一一对应 STEP1:刷新所有未发送到 ...

  3. JavaScript高级程序设计(第三版) 6/25

    第六章面向对象的程序设计 1.定义只有在内部才用的特性(attribute)时,描述了属性(property)的各种特征.这些特性是为了实现JavaScript引擎用的,因此在JavaScript中不 ...

  4. JVM笔记-GC常用参数设置

    GC常用参数 -Xmn -Xms -Xmx -Xss 年轻代 最小堆 最大堆 栈空间, -Xms -Xmx 一般设置成一样大小, -XX:+UseTLAB 使用TLAB,默认打开 -XX:+Print ...

  5. PHP diskfreespace() 函数

    定义和用法 diskfreespace() 函数返回指定目录的可用空间,以字节为单位. 该函数是 disk_free_space() 函数的别名. 语法 diskfreespace(directory ...

  6. luogu P4284 [SHOI2014]概率充电器 期望 概率 树形dp

    LINK:概率充电器 大概是一个比较水的题目 不过有一些坑点. 根据期望的线性性 可以直接计算每个元件的期望 累和即为答案. 考虑统计每一个元件的概率的话 那么对其有贡献就是儿子 父亲 以及自己. 自 ...

  7. 字节跳动2020-ByteCamp暑期夏令营研发组习题

    概要 本文主要是记录字节2020夏令营的笔试习题,解答部分待日后不断完善. 选择题部分记录不是很完全,剩下没有被收录的大都偏容易. 单项选择题 箱子里有20个红球,18个白球,逐一随机抽取球,问整个过 ...

  8. windows下使用redis命令行模式查询数据

    背景:redis的火,就像java一样,对于测试人员来说,使用它就需要好好搞下,现在就整理下命令行模式,来查询获取自己想要的值: 命令行连接命令:redis-cli -h 主机名 -p 端口号 -a ...

  9. 一个Java方法能使用多少个参数?

    我最近给我fork的项目QuickTheories增加了一个接口: @FunctionalInterface public interface QuadFunction<A, B, C, D, ...

  10. 华为云GaussDB(DWS)内存知识点,你知道吗?

    前言 在日常数据库的使用中,难免会遇到一些内存问题.此次博文主要向大家分享一些华为云数仓GaussDB(DWS)内存的基本框架以及基本视图的使用,以便遇到内存问题后可以有一个基本的判断. 注意,本篇博 ...