synchronized

Thread和Object类中的重要方法详解

為{幸葍}努か 提交于 2020-03-03 12:01:05
Thread和Object类中的重要方法详解 方法概览 wait、notify、notifyAll 作用、用法 :阻塞阶段、唤醒阶段、遇到中断 直到以下四种情况之一发生时,才会被唤醒 另一个线程调用这个对象的notify()方法且刚好被唤醒的是本线程 另一个线程调用这个对象的notifyAll()方法 过了wait(long timeout)规定的超时时间,如果传入0就是永久等待; 线程自身调用了interrupt() 代码演示:展示wait和notify的基本用法 研究代码执行顺序 证明wait释放锁 public class Wait { public static Object object = new Object ( ) ; static class Thread1 extends Thread { @Override public void run ( ) { synchronized ( object ) { System . out . println ( Thread . currentThread ( ) . getName ( ) + "开始执行了" ) ; try { object . wait ( ) ; } catch ( InterruptedException e ) { e . printStackTrace ( ) ; } System .

Java 并发编程(一)

谁说我不能喝 提交于 2020-03-02 13:13:08
#Java 并发编程(一) ##同步容器 1.Vector,Hashtable。 实现线程安全的方式是:将它们的状态封装起来,并对每个共有方法进行同步,使得每次只有一个线程能访问容器的状态。使用了Java监视器模式。 2.Vector代码分析 //根据下标获取数据,都是使用synchronized实现同步 public synchronized E get(int index) { if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); return elementData(index); } //添加数据 public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; } //扩容 private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (

多线程学习笔记(七)

喜夏-厌秋 提交于 2020-03-02 12:36:00
在使用synchronized时,当一个线程得到一个对象锁后,再次请求此对象锁时是可以再次得到该对象锁的.这也证明在一个synchronized方法/块的内部调用本类的其他synchronized方法/块时,是永远可以得到锁的. public class ThreadReenter { synchronized public void firstService() { System.out.println("This is the first service!"); secondService(); } synchronized public void secondService() { System.out.println("This is the second service!"); thirdService(); } synchronized public void thirdService() { System.out.println("This is the third service!"); } } public class FirstThread extends Thread { @Override public void run(){ ThreadReenter threadReenter = new ThreadReenter(); threadReenter

java的synchronized关键字

做~自己de王妃 提交于 2020-03-02 11:49:28
public class SynMethod { private static final Object staticLockObj = new Object(); /** * 对象锁,代码级别,同一对象争用该锁,this为SynMethod实例,synchronized的锁绑定在this对象上 */ public void method1() { synchronized (this) { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + " synchronized loop " + i); } } } /** * 对象锁,方法级别,同一对象争用该锁,普通(非静态)方法,synchronized的锁绑定在调用该方法的对象上,与上一个写法含义一致 */ public synchronized void method2() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + " synchronized loop " + i); } } /** * 对象锁,代码级别,同一类争用该锁,绑定在staticLockObj上,不同SynMethod实例

java进阶(6)之从硬件底层剖析synchronized/volatile原理

不羁的心 提交于 2020-03-02 11:06:02
已知: java 中的 synchronized 关键字能保证可见性,有序性,原子性; volatile 关键字能保证可见性,有序性。 问题: 为什么 java 中的并发,在硬件层面不能保证,非要在 JVM 里处理呢? 它们在硬件层面是如何对应保证的呢? java 层面为啥要加这两个关键字才能保证 java 的并发特性呢? 指令重排序无法保证有序性 java 中的一行行代码,对应到硬件层面,就是一个个指令,现代处理器为了加快编译速度,有可能会乱序执行指令,这样也就无法保证代码的有序性了。 现代CPU缓存模型无法保证可见性和原子性 图解CPU缓存模型 简化版CPU缓存模型请移步: java进阶(4)之volatile关键字深入详解 1. 高速缓存中的 tag 表示数据所对应的内存地址, cacheline 表示数据本身, flag 表示数据状态(E表示 exclusive 写,S表示 shared 读) 2. Java 层面的读写数据,对应到硬件层面,就是主内存/高速缓存的读写; 3. 处理器与处理器之间的数据交互,或者说处理器与主内存的数据交互,是通过总线的嗅探机制来实现的,也可以说是缓存一致性协议(我把嗅探机制类比成 java 层面的 EventBus ); 4. 现代 CPU 为了加快读写速度,加入了写缓冲器和无效队列,但是这样的话,数据只有读写完成了,才能进入到高速缓存

lock和wait+signal

送分小仙女□ 提交于 2020-03-02 02:38:00
lock和wait+signal 在编程中,我们经常使用多线程来提升性能,所以这就涉及到 互斥和同步 的问题了。而在编程中,我们一般都是通过如下方式来完成多线程的互斥和同步: lock | unlock signal + wait(timeout) join sleep C语言 在Linux C编程中,我们通常使用 pthread 类库来完成跨平台的多线程控制,如下是几个常用的API: pthread_mutex_lock():占有互斥锁(阻塞操作) pthread_mutex_unlock(): 释放互斥锁 pthread_cond_signal(): 唤醒第一个调用pthread_cond_wait()而进入睡眠的线程 pthread_cond_wait(): 等待条件变量的特殊条件发生 pthread_cond_timedwait():等待条件变量的特殊条件发生或者timeout pthread_join():阻塞当前的线程,直到另外一个线程运行结束 sleep() : 休眠固定时间, 不过这个API是Linux原生提供,不能跨平台。 注意:**pthread类库是glibc(绝大多数Linux平台标准C库。)的一部分。这些功能都是通过中断号进入内核来完成的,而非仅仅做了Linux兼容API。**具体可见 glibc-2.23\sysdeps\nacl\nacl

原子变量与synchronized详细解释

孤者浪人 提交于 2020-03-02 02:36:24
AtomicInteger,一个提供原子操作的Integer的类。在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。 要使用多处理器系统的功能,通常需要使用多线程构造应用程序。但是正如任何编写并发应用程序的人可以告诉你的那样,要获得好的硬件利用率,只是简单地在多个线程中分割工作是不够的,还必须确保线程确实大部分时间都在工作,而不是在等待更多的工作,或等待锁定共享数据结构。而synchronized来控制并发就需要去等待这个锁资源,这步是非常消耗资源的,处理的吞吐量也就下去了。而java的concurrent 并发包提供的AtomicInteger就提供CAS原理避免了锁等待,具体的实现是通过UnSafe类来直接操作底层的硬件资源。 cpu 硬件同步原语(compare and swap) 支持并发的第一个处理器提供原子的测试并设置操作,通常在单位上运行这项操作。现在的处理器(包括 Intel 和 Sparc 处理器)使用的最通用的方法是实现名为 比较并转换或 CAS 的原语。(在 Intel 处理器中,比较并交换通过指令的 cmpxchg 系列实现。PowerPC 处理器有一对名为“加载并保留”和“条件存储”的指令,它们实现相同的目地;MIPS 与

多线程进阶——JUC并发编程之Synchronized底层实现概论🔥

 ̄綄美尐妖づ 提交于 2020-03-02 01:07:17
1、Synchronized简介 Java中提供了两种实现同步的基础语义: synchronized 方法和 synchronized 块 ,下面我们来操作一番: public class SyncTest { public void syncBlock(){ synchronized (this){ System.out.println("sync block balabala...."); } } public synchronized void syncMethod(){ System.out.println("sync method hahaha...."); } public static void main(String[] args) { } } 将SyncTest.java 编译为SyncTest,.class文件,我们使用 javap -v SyncTest.class 查看class文件对应的JVM字节码信息。这里我使用的是JVM版本是JDK1.8。 { ... public void syncBlock(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=1 0: aload_0 1: dup 2: astore_1 3: monitorenter 4:

Java 并发编程:核心理论

此生再无相见时 提交于 2020-03-01 20:23:14
并发编程是Java程序员最重要的技能之一,也是最难掌握的一种技能。它要求编程者对计算机最底层的运作原理有深刻的理解,同时要求编程者逻辑清晰、思维缜密,这样才能写出高效、安全、可靠的多线程并发程序。本系列会从线程间协调的方式(wait、notify、notifyAll)、Synchronized及Volatile的本质入手,详细解释JDK为我们提供的每种并发工具和底层实现机制。在此基础上,我们会进一步分析java.util.concurrent包的工具类,包括其使用方式、实现源码及其背后的原理。本文是该系列的第一篇文章,是这系列中最核心的理论部分,之后的文章都会以此为基础来分析和解释。 一、共享性   数据共享性是线程安全的主要原因之一。如果所有的数据只是在线程内有效,那就不存在线程安全性问题,这也是我们在编程的时候经常不需要考虑线程安全的主要原因之一。但是,在多线程编程中,数据共享是不可避免的。最典型的场景是数据库中的数据,为了保证数据的一致性,我们通常需要共享同一个数据库中数据,即使是在主从的情况下,访问的也同一份数据,主从只是为了访问的效率和数据安全,而对同一份数据做的副本。我们现在,通过一个简单的示例来演示多线程下共享数据导致的问题: 代码段一: package com.paddx.test.concurrent; public class ShareData {

线程间的通信

扶醉桌前 提交于 2020-03-01 16:35:53
一,概述。    1.什么叫做线程间通信: 在1个进程中,线程往往不是孤立存在的,线程之间需要一些协调通信,来共同完成一件任务。也就是通过一定的方法来实现线程间的“交流”。   2.线程间通信的体现:     - 1个线程传递数据给另1个线程     - 在1个线程中执行完特定任务后,转到另1个线程继续执行任务 二,线程通信的方法。    Object类中相关的方法有两个notify方法和三个wait方法:notify() / notifyAll() / wait()   因为wait和notify方法定义在Object类中,因此会被所有的类所继承。这些方法都是 final 的,即它们都是不能被重写的,不能通过子类覆写去改变它们的行为。    1.wait()方法。     语法:锁对象.wait()   特点:wait()方法的调用使得当前线程必须要等待,直到另外一个线程调用notify()或者notifyAll()方法。      wait()方法的调用必须在同步的前提下。(因为该方法是要用锁对象调用,而只有在同步的情况下才有锁)      wait()方法的调用会导致锁的释放。   线程调用wait()方法,释放它对锁的拥有权,然后等待另外的线程来通知它(通知的方式是notify()或者notifyAll()方法),这样它才能重新获得锁的拥有权和恢复执行。要确保调用wait(