synchronized

synchronized实现原理

一个人想着一个人 提交于 2020-03-23 22:12:53
3 月,跳不动了?>>> 目前在Java中存在两种锁机制:synchronized和Lock。数据同步需要依赖锁,那锁时如何实现的呢,synchronized给出的答案是软件层面依赖JVM,而Lock给出的方案是在硬件层面依赖特殊的CPU指令。 下面先介绍synchronized的实现: synchronized 是关键字,即使有了Lock接口(Lock能够实现synchronized能够实现的所有功能),使用的还是非常广泛。其应用层的语义是可以把任何一个非nul对象作为锁,当synchronized作用在方法上时,锁住的对象是实例对象(this);当作用在静态方法时锁住的对象时对象对应的Class实例,因为Class数据存在于永久带,因此静态方法锁相当于类的一个全局锁;当synchronized作用于某一个对象实例时,锁住的便是对应的代码块。在JVM实现中,所有一个专门的名字:对象监视器 线程状态与状态的转换 当多个线程同时请求某个对象监视器时,对象监视器会设置几种状态来区分请求的线程 Contention List:所有请求锁的线程将被首先放置到竞争队列。Contention List是一个虚拟队列,原因在于Contention List是一个由Node及next指针逻辑构成,并不存在一个Queue的数据结构。ContentionList是一个后进先出(LIFO)队列。

Java多线程同步方法

◇◆丶佛笑我妖孽 提交于 2020-03-22 18:50:35
一、同步方法   即有 synchronized关键字修饰的方法 。 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。 注: synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类。 二、同步代码块   即有synchronized关键字修饰的语句块。 被synchronized关键字修饰的语句块会自动被加上内置锁,从而实现同步 代码如: synchronized(object){ } 注:同步是一种高开销的操作,因此应该尽量减少同步的内容。 通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。 线程在执行同步方法时是具有排它性的。 当任意一个线程进入到一个对象的任意一个 同步方法 时,这个对象的所有同步方法都被锁定了,在此期间,其他任何线程都不能访问这个对象的任意一个同步方法,直到这个线程执行完它所调用的同步方法并从中退出,从而导致它释放了该对象的同步锁之后。 在一个对象被某个线程锁定之后,其他线程是可以访问这个对象的所有非同步方法的。 同步块:同步块是通过锁定一个指定的对象,来对同步块中包含的代码进行同步; 而同步方法是对这个方法块里的代码进行同步,而这种情况下锁定的对象就是同步方法所属的主体对象自身。如果这个方法是静态同步方法呢

Java 线程与多线程

对着背影说爱祢 提交于 2020-03-22 17:46:55
Java是一门支持多线程的编程语言! 什么是进程? 计算机中内存、处理器、IO等资源操作都要为进程进行服务。 一个进程上可以创建多个线程,线程比进程更快的处理单元,而且所占用的资源也小,多线程的应用也是性能最高的。 Java的多线程实现:(三种方式)   在Java中实现多线程有两种途径:     1、继承Thread类     2、实现Runnable接口     3、实现Callable接口 继承Thread类: class MyThread extends Thread { //继承Thread 即 多线程类【线程操作主类】 } ps:在Java中,任何一个类继承了Thread类,都视为该类为多线程类。 在Java程序中都有一个“起点”即开始的地方;那么多线程类也有一个“起点”—— run()方法 ,也就是说在多线程的每个主体类中都必须要覆写Thread类中所提供的 run() 方法 public void run() ; run()方法没有提供参数和返回值,那么也就表示了线程一旦开始就要一直执行,不能够返回内容。 import sun.security.mscapi.KeyStore.MY; class MyThread extends Thread { //继承Thread 即 多线程类 private String name ; public MyThread

说说Java中的那些锁

自闭症网瘾萝莉.ら 提交于 2020-03-22 03:54:22
  在学习Java锁的时候,总觉的比较含糊,感觉一直没有系统的消化理解。所以决定重新梳理一下java相关的锁。     本质来说只有两种锁,乐观锁和悲观锁,其他所谓的可重入、自旋、偏向/轻量/重量锁等,都是锁具有的一些特点或机制。目的就是在数据安全的前提下,提高系统的性能。 乐观锁    乐观锁,顾名思义,就是说在操作共享资源时,它总是抱着乐观的态度进行,它认为自己可以成功地完成操作。但实际上,当多个线程同时操作一个共享资源时,只有一个线程会成功,那么失败的线程呢?它们不会像悲观锁一样在操作系统中挂起,而仅仅是返回,并且系统允许失败的线程重试,也允许自动放弃退出操作。所以,乐观锁相比悲观锁来说,不会带来死锁、饥饿等活性故障问题,线程间的相互影响也远远比悲观锁要小。更为重要的是,乐观锁没有因竞争造成的系统开销,所以在性能上也是更胜一筹。   CAS 是实现乐观锁的核心算法,它包含了 3 个参数:V(需要更新的变量)、E(预期值)和 N(最新值)。只有当需要更新的变量等于预期值时,需要更新的变量才会被设置为最新值,如果更新值和预期值不同,则说明已经有其它线程更新了需要更新的变量,此时当前线程不做操作,返回 V 的真实值。    如何实现原子操作   在 JDK 中的 concurrent 包中,atomic 路径下的类都是基于 CAS 实现的。AtomicInteger 就是基于

ConcurrentHashMap源码解析(1.8)

末鹿安然 提交于 2020-03-20 07:58:47
一、简介 上篇文章 详细介绍了HashMap的源码及原理,本文趁热打铁继续分析ConcurrentHashMap的原理。 首先在看本文之前,希望对HashMap有一个详细的了解。不然看直接看ConcurrentHashMap的源码还是有些费劲的。 相信对HashMap,HashTable有一定了解,应该知道HashMap是不具备线程安全性的,在resize时会丢数据(JDK8),而HashTable虽然保证了线程安全性,但是其是通过给每个方法加Synchronized关键字达到的同步目的。但是都知道Synchronized在竞争激烈的多线程并发环境中,在性能上的表现是非常不如人意的。那在高并发环境中HashMap如何保证线程安全而又不浪费太多性能呢?答案就是Java J.U.C并发包中的ConcurrentHashMap。 依然开局一张图。JDK8中的ConcurrentHashMap数据结构。 呃呵,和HashMap的结构是一样的,没错在数据结构层面,ConcurrentHashMap和HashMap是完全一样的。有了这个基础继续往下看。 二、历史版本 ConcurrentHashMap的历史版本大致分界线在JDK8。也就是可以分为JDK8和JDK8以前版本。 数据结构的区别 在JDK8之前HashMap没有引入红黑树,同样的ConcurrentHashMap也没有引入红黑树

【线程锁 Synchronized与ReentrantLock 示例】

萝らか妹 提交于 2020-03-20 00:13:25
前言: 之前一直对线程锁不理解,去网上找了很多讲解Synchronized关键字和ReentrantLock的帖子,大致了解了用法,写个小程序记录一下。有不足和错误欢迎留言评论,大家一起学习进步。 一、为什么要用线程锁 Java多线程同时处理任务会显著提高工作效率。但是,如果多个线程同时操作某一资源,可能会导致数据的不同步,引发错误。因此对于某些资源我们要对线程进行控制,同一时间只允许单个线程进行操作。这时我们就需要使用线程锁。 场景: 书店生产书,直到书总量达到10本,顾客买书,总共要买10本 书店:书店只要书不足10本就一直生产,直到书店内书个数达到10,停止生产,如果此时有书被顾客买走就继续生产,直至存货10本... 顾客:只要书店有书就从书店购买,没有书就停止购买,等有书产出就继续,直到购买10本 二、Synchronized关键字实现线程锁 书店: public class SynchronizedProviderThread extends Thread { public static List<String> books=new ArrayList<String>(); public static int MAX_BOOK_NUM=10; public void run(){ try{ while(!Thread.interrupted()){

java线程池之synchronized锁

谁说胖子不能爱 提交于 2020-03-20 00:11:59
1 //Object 定义了一个引用类型的对象用于加锁 2 static Object Lock = new Object(); 3 //定义一个int类型变量0做初始值 4 static int iCheck = 0; 5 6 public static void main(String[] args) { 7 //第一个线程 8 int a = 0; 9 //创建一个数组保存打印的数值 10 List<Integer> list = new ArrayList<>(); 11 //设置线程池大小为4 12 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4); 13 //i从0开始递增1,直到小于1000跳出循环 14 for (int i = 0; i < 1000; i++) { 15 list.add(a); 16 a++; 17 } 18 //循环触发4个任务丢给线程池处理 19 for (int i = 0; i < list.size(); i++) { 20 int z = list.get(i); 21 //把任务交给线程池 22 fixedThreadPool.execute(() -> { 23 Test(z); 24 }); 25 } 26 } 27 28 public

java线程(2)--同步和锁

醉酒当歌 提交于 2020-03-20 00:11:24
参考转载:http://rainyear.iteye.com/blog/1734311 http://turandot.iteye.com/blog/1704027 http://www.cnblogs.com/fguozhu/articles/2657904.html http://lavasoft.blog.51cto.com/62575/99155 http://www.cnblogs.com/dolphin0520/p/3923167.html 1.线程的内存模型 Java作为平台无关性语言,JLS(Java语言规范)定义了一个统一的内存管理模型 JMM (Java Memory Model),JMM屏蔽了底层平台内存管理细节,在多线程环境中必须解决可见性和有序性的问题。JMM规定了jvm有 主内存 (Main Memory)和 工作内存 (Working Memory) ,主内存存放程序中所有的类实例、静态数据等变量,是多个线程共享的,而工作内存存放的是该线程从主内存中拷贝过来的变量以及访问方法所取得的局部变量,是每个线程私有的其他线程不能访问,每个线程对变量的操作都是以先从主内存将其拷贝到工作内存再对其进行操作的方式进行,多个线程之间不能直接互相传递数据通信,只能通过共享变量来进行。 重要的图片看三遍,从三个内存模型的文章中摘出的图片含义是一致的。即: 1

java线程基础知识----线程与锁

非 Y 不嫁゛ 提交于 2020-03-20 00:10:28
  我们上一章已经谈到java线程的基础知识,我们学习了Thread的基础知识,今天我们开始学习java线程和锁。   1.  首先我们应该了解一下Object类的一些性质以其方法,首先我们知道Object类的是java的顶层类,所有的类都集成自Object类,包括string和数组。而且每一个Object都有一个锁,同一时间只能有一个线程暂用这个对象的锁。这是我们今天学习的前提条件,至于Object的一些方法我们在后面的章节中会进行学习。   2.  java锁之synchronized: 想必大家都知道java的synchronized关键字,在我看来这是锁操作中相对简单的方法,但是对事物我总有一个定义“简单的就是可扩展性差的”,下面我们将了解synchronized关键字的用法: A. 入门基础实例: 举一个经典的售票例子,就是同时有2个窗口售票(当然是电子票),而且票的数量是一定的,假设20张。两个窗口之间售票相互独立。我们应该怎么实现? public class ThreadTest { public static void main(String[] args) throws InterruptedException{ Thread1 thread1 = new Thread1(); Thread threadA = new Thread(thread1);

5.线程的八大核心基础知识之Thread和Object类中的重要方法详解

那年仲夏 提交于 2020-03-18 18:14:17
一.概述 二.方法概览 三.wait,notify,notifyAll方法详解 1.作用和用法:阻塞阶段、唤醒阶段、遇到中断 wait作用是释放锁,当前线程进入等待, notify和notifyAll作用是通知等待线程可以执行 wait,notify,notifyAll都必须放到同步代码块中 (1)wait和notify基本用法展示: 首先thread1线程拿到object对象锁住object后执行进入到wait方法后释放了锁,进入了等待状态 然后thread2线程拿到object对象锁住object后执行notify通知等待的线程可以运行了,然后继续执行run方法到结束 最后thread1拿到锁继续执行run方法到结束 /** * 展示wait和notify的基本用法:1.研究代码执行顺序 2.证明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