很多刚接触多线程编程的开发者,虽然意识到了并发访问可变变量需要加锁,但是对于锁的范围、加锁的时机和锁的协同缺乏认识,往往会导致出现一些问题。下面笔者就结合Netty的代码来讲解下这方面的知识。

打开ForkJoinTask,我们学习一些多线程同步和协作方面的技巧。首先是当条件不满足时阻塞某个任务,直到条件满足后再继续执行,代码如图21-4所示。

重点看框线中的代码,首先通过循环检测的方式对状态变量status进行判断,当它的状态大于等于0时,执行wait(),阻塞当前的调度线程,直到status小于0,唤醒所有被阻塞的线程,继续执行。这个方法有以下三个多线程的编程技巧需要说明。

图21-4  多线程协作

(1)wait方法用来使线程等待某个条件,它必须在同步块内部被调用,这个同步块通常会锁定当前对象实例。下面是这个模式的标准使用方式。

synchronized(this)

{

While(condition)

Object.wait;

......

}

(2)始终使用wait循环来调用wait方法,永远不要在循环之外调用wait方法。这样做的原因是尽管并不满足被唤醒条件,但是由于其他线程调用notifyAll()方法会导致被阻塞线程意外唤醒,此时执行条件并不满足,它将破坏被锁保护的约定关系,导致约束失效,引起意想不到的结果。

(3)唤醒线程,应该使用notify还是notifyAll?当你不知道究竟该调用哪个方法时,保守的做法是调用notifyAll唤醒所有等待的线程。从优化的角度看,如果处于等待的所有线程都在等待同一个条件,而每次只有一个线程可以从这个条件中被唤醒,那么就应该选择调用notify。

当多个线程共享同一个变量的时候,每个读或者写数据的操作方法都必须加锁进行同步,如果没有正确的同步,就无法保证一个线程所做的修改被其他线程共享。未能同步共享变量会造成程序的活性失败和安全性失败,这样的失败通常是难以调试和重现的,它们可能间歇性地出问题,可能随着并发的线程个数增加而失败,也可能在不同的虚拟机或者操作系统上存在不同的失败概率。因此,务必要保证锁的正确使用。下面这个案例,就是个典型的错误应用。

int size = 0;

public synchronized void increase()

{

size++;

}

public int current()

{

Return size;

}

Netty的并发编程实践1:正确使用锁的更多相关文章

  1. Netty的并发编程实践4:线程安全类的应用

    在JDK1.5的发行版本中,Java平台新增了java.util.concurrent,这个包中提供了一系列的线程安全集合.容器和线程池,利用这些新的线程安全类可以极大地降低Java多线程编程的难度, ...

  2. Netty的并发编程实践3:CAS指令和原子类

    互斥同步最主要的问题就是进行线程阻塞和唤醒所带来的性能的额外损耗,因此这种同步被称为阻塞同步,它属于一种悲观的并发策略,我们称之为悲观锁.随着硬件和操作系统指令集的发展和优化,产生了非阻塞同步,被称为 ...

  3. Netty的并发编程实践2:volatile的正确使用

    长久以来大家对于volatile如何正确使用有很多的争议,既便是一些经验丰富的Java设计师,对于volatile和多线程编程的认识仍然存在误区.其实,volatile的使用非常简单,只要理解了Jav ...

  4. Netty的并发编程实践5:不要依赖线程优先级

    当有多个线程同时运行的时候,由线程调度器来决定哪些线程运行.哪些等待以及线程切换的时间点,由于各个操作系统的线程调度器实现大相径庭,因此,依赖JDK自带的线程优先级来设置线程优先级策略的方法是错误和非 ...

  5. 并发编程实践五:ReentrantLock

    ReentrantLock是一个可重入的相互排斥锁,实现了接口Lock,和synchronized相比,它们提供了同样的功能.但ReentrantLock使用更灵活.功能更强大,也更复杂.这篇文章将为 ...

  6. Java并发编程实践

    最近阅读了<Java并发编程实践>这本书,总结了一下几个相关的知识点. 线程安全 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任 ...

  7. [Java 并发] Java并发编程实践 思维导图 - 第一章 简单介绍

    阅读<Java并发编程实践>一书后整理的思维导图.

  8. [Java 并发] Java并发编程实践 思维导图 - 第二章 线程安全性

    依据<Java并发编程实践>一书整理的思维导图.

  9. 并发编程实践三:Condition

    Condition实例始终被绑定到一个锁(Lock)上.Lock替代了Java的synchronized方法,而Condition则替代了Object的监视器方法,包含wait.notify和noti ...

随机推荐

  1. Effective Java 之-----精确的答案与double&float

    题目: 假设你口袋里有1$,看到货架上有一排美味的糖果,标价分别为0.10$,0.20$,0.30$...1$,你打算从标价为0.10$的糖果开始买起,每种买一颗,一直到不能支付货架上下一种价格的糖果 ...

  2. php应用pack函数转unicode为utf8

    因为时常用到json_encode去处理数据,json_encode在处理字符串遇上中文时,会把中文转换成\u5371这种格式的字符串,如果想让它能正常显示中文,则可以用pack打包函数进行处理. 以 ...

  3. CDlinux制作U盘启动盘,打造自己的口袋系统

    工具: 1.8G或以上U盘一枚: 2.CDlinux0.9.7.1镜像文件,注意其他版本不一定能成功(传送门http://pan.baidu.com/s/1o7P6Gu2): 3.UltraISO或U ...

  4. BZOJ 2084: [Poi2010]Antisymmetry [Manacher]

    2084: [Poi2010]Antisymmetry Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 609  Solved: 387[Submit] ...

  5. Java数据结构和算法(十五)——无权无向图

    前面我们介绍了树这种数据结构,树是由n(n>0)个有限节点通过连接它们的边组成一个具有层次关系的集合,把它叫做“树”是因为它看起来像一棵倒挂的树,包括二叉树.红黑树.2-3-4树.堆等各种不同的 ...

  6. python学习资料链接

    1.入门与量化:https://www.v2ex.com/t/257297

  7. Leetcode刷题C#版之Toeplitz Matrix

    题目: Toeplitz Matrix A matrix is Toeplitz if every diagonal from top-left to bottom-right has the sam ...

  8. zabbix安装步骤

    第一步:安装环境 Zabbix要求的环境 组件 版本要求 Apache版本 1 .3.1 2 MySQL版本 5.0.3 PHP版本 5.4.0 本次安装的环境 组件 版本要求 操作系统 CentOS ...

  9. Rsync(远程同步): linux中Rsync命令的实际示例

    rsync的 ( 远程同步 )为在Linux / Unix系统局部 拷贝和同步文件和目录远程以及一个最常用的命令. 随着rsync命令的帮助,您可以复制并在目录中远程和本地同步数据,在磁盘和网络,进行 ...

  10. 启动MySql提示:The server quit without updating PID file(…)失败

    1.可能是/usr/local/mysql/data/rekfan.pid文件没有写的权限解决方法 :给予权限,执行 "chown -R mysql:mysql /var/data" ...