synchronized

synchronized和lock比较浅析

…衆ロ難τιáo~ 提交于 2020-01-30 00:53:26
synchronized是基于jvm底层实现的数据同步,lock是基于Java编写,主要通过硬件依赖CPU指令实现数据同步。下面一一介绍 一、 synchronized 的实现方案   1. synchronized能够把任何一个非null对象当成锁,实现由两种方式:   a.当synchronized作用于非静态方法时,锁住的是当前对象的事例,当synchronized作用于静态方法时,锁住的是class实例,又因为 Class的相关数据存储在永久带,因此静态方法锁相当于类的一个全局锁。   b.当 synchronized作用于一个对象实例时,锁住的是对应的代码块。   2.synchronized锁又称为对象监视器(object)。 3.当多个线程一起访问某个对象监视器的时候,对象监视器会将这些请求存储在不同的容器中。   > Contention List:竞争队列,所有请求锁的线程首先被放在这个竞争队列中   > Entry List: Contention List中那些有资格成为候选资源的线程被移动到 Entry List中   > Wait Set:哪些调用 wait方法被阻塞的线程被放置在这里   > OnDeck:任意时刻,最多只有一个线程正在竞争锁资源,该线程被成为 OnDeck   > Owner:当前已经获取到所资源的线程被称为 Owner   >

synchronized

一世执手 提交于 2020-01-29 23:44:56
什么是synchronized synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。它包括两种用法:synchronized 方法和 synchronized 块。 Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍可以访问该object中的非加锁代码块。 为什么使用synchronized synchronized的用法 1.同步非静态方法(实例方法) public class synchronizedTest implements Runnable { static int i =0; public synchronized void increase(){ i++; } @Override

Java多线程同步之ThreadLocal与Synchromized

半世苍凉 提交于 2020-01-29 23:05:28
前言: ThreadLocal和Synchronized都是为了解决多线程中相同变量的访问冲突问题,只是二者处理问题的思路和角度不同。 ThreadLocal是Java类,是通过每个线程单独一份存储空间,牺牲空间来弥补时间来解决多线程访问冲突,ThreadLocal具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问到想要的值。 Synchronized是Java保留关键字,通过线程等待,牺牲时间来解决访问冲突。依靠JVM的锁机制来实现临界区的函数或者变量的访问中的原子性。在同步机制中,通过对象的锁机制保证同一时间只有一个线程的访问变量,此时被用作锁机制的变量被多个线程共享。 代码 Synchronized public class SqlConnectionUtil { private static SqlPool instance=null; public static synchronized SqlConnection getInstance(){ if(instance==null) instance=new SqlPool(); return instance.getSqlConnection(); } ThreadLocal public class SqlConnectionUtil { private static ThreadLocal

Volatile关键字实现原理

混江龙づ霸主 提交于 2020-01-29 21:36:56
1、 认识 volatile 关键字 volatile是java提供的一种同步手段,只不过它是轻量级的同步,为什么这么说,因为volatile只能保证多线程的内存可见性,不能保证多线程的执行有序性。而最彻底的同步要保证有序性和可见性,例如synchronized。任何被volatile修饰的变量,都不拷贝副本到工作内存,任何修改都及时写在主存。因此对于volatile修饰的变量的修改,所有线程马上就能看到,但是volatile不能保证对变量的修改是有序的。 程序的局部执行原理 Java内存模型 jvm将内存组织为主内存和工作内存两个部分。 主内存主要包括本地方法区和堆。每个线程都有一个工作内存,工作内存中主要包括两部分,一个是属于该线程私有的栈,另一个是对主存部分变量拷贝的寄存器(包括程序计数器PC和cpu工作的高速缓存区) 1) 主存中的数据所有线程都可以访问(共享数据) 2) 每个线程都有自己的工作空间,(本地内存)(私有数据) 3) 工作空间数据:局部变量、内存的副本 4) 线程不能直接修改内存中的数据,只能读到工作空间来修改,修改完成后刷新到内存 Volatile 关键字的语义分析    volatile作用:让其他线程能够马上感知到某一线程多某个变量的修改 (1)保证可见性 对共享变量的修改,其他的线程马上能感知到 不能保证原子性 读、写、( i++) (2)保证有序性

死锁问题

江枫思渺然 提交于 2020-01-29 17:39:25
代码如下 package lock; public class DeadLock { public static Integer l = 5; public static Integer r = 6; public static void main(String[] args) { new Thread(new Thread4()).start(); new Thread(new Thread3()).start(); } } class Thread3 implements Runnable{ @Override public void run() { synchronized (DeadLock.l){ try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (DeadLock.r){ System.out.println("Thread3 is running"); } } } } class Thread4 implements Runnable{ @Override public void run() { synchronized (DeadLock.r){ try { Thread.sleep(2000); } catch

多线程的安全问题

让人想犯罪 __ 提交于 2020-01-29 12:59:17
一,多线程安全问题分析 1、线程安全问题出现的原因: (1)多个线程操作共享的数据; (2)线程任务操作共享数据的代码有多条(多个运算)。 在 多线程 中 ,当CPU在执行的过程中,可能随时切换到其他的线程上执行。比如当线程1正在执行时,由于CPU的执行权被线程2抢走,于是线程1停止运行进入就绪队列,当线程2运行完,释放CPU的使用权,此时当线程1再次获得CPU的执行 权时,由于线程2将 某些 共享数据 的值已改变,所以此时线程1继续运行就会出现错误隐患。 2 、 举例分析: 假设有三个线程在抢票。当线程1抢到CPU执行权,先对系统票数进行判断,发现票数是大于0的,接着准备购票,但由于其他原因,该线程1被阻塞,CPU执行权被线程2抢到,CPU开始执行线程2,线程2同样先对票数进行判断,如果大于0,就进行购票, 但由于其他原因,该线程2也被阻塞, CPU执行权被线程3抢到,CPU开始执行线程3,线程3同样先对票数进行判断,如果大于0,就进行购票,由于需求较大,系统的票全部被线程3购完,此时线程3执行完毕释放了cpu执行权。这时CPU执行权又被线程1抢到,CPU开始执行线程1代码,因为之前线程1已经对系统票数进行判断过,所以此时不会再继续判断,而是直接购票,但由于系统的票已全部被线程3购完,这时线程1再继续购买就会出现票数错误(如用户买的票号为0号票或-1号票,而现实中不存在0号票和

synchronized

最后都变了- 提交于 2020-01-29 04:53:57
使用方法 修饰一个方法,被修饰的方法称为同步方法,其作用范围是整个方法 修饰一个代码块,被修饰的代码块称为同步代码块,作用范围是大括号{}括起来的代码 修饰一个静态方法,作用范围是整个静态方法 修饰代码块:锁的是括号内的对象 class SynchronizedTest implements Runnable{ private static int counter = 1; @Override public void run() { String startDate = Synchronized.getCurrentDate(); synchronized (this) { for (int i = 0; i < 5; i++) { try { System.out.println("线程 :" + Thread.currentThread().getName() + " 当前计数器 :" + (counter++)); System.out.println("开始时间 :" + startDate + " 当前时间 :" + Synchronized.getCurrentDate()); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static

Java 并发:线程基础

怎甘沉沦 提交于 2020-01-29 03:57:22
线程状态转换 新建(New) 创建后尚未启动。 可运行(Runnable) 可能正在运行,也可能正在等待 CPU 时间片。 包含了操作系统线程状态中的 Running 和 Ready。 阻塞(Blocking) 等待获取一个排它锁,如果其线程释放了锁就会结束此状态。 无限期等待(Waiting) 等待其它线程显式地唤醒,否则不会被分配 CPU 时间片。 限期等待(Timed Waiting) 无需等待其它线程显式地唤醒,在一定时间之后会被系统自动唤醒。 调用 Thread.sleep() 方法使线程进入限期等待状态时,常常用“使一个线程睡眠”进行描述。 调用 Object.wait() 方法使线程进入限期等待或者无限期等待时,常常用“挂起一个线程”进行描述。 睡眠和挂起是用来描述行为,而阻塞和等待用来描述状态。 阻塞和等待的区别在于,阻塞是被动的,它是在等待获取一个排它锁。而等待是主动的,通过调用 Thread.sleep() 和 Object.wait() 等方法进入。 死亡(Terminated) 可以是线程结束任务之后自己结束,或者产生了异常而结束。 线程使用方式 有三种使用线程的方法: 实现 Runnable 接口; 实现 Callable 接口; 继承 Thread 类。 实现 Runnable 和 Callable 接口的类只能当做一个可以在线程中运行的任务

Java线程使用之同步机制

断了今生、忘了曾经 提交于 2020-01-29 00:07:54
视频讲解:https://www.bilibili.com/video/av75932256?p=429 lock锁的讲解:https://www.bilibili.com/video/av75932256?p=437 线程安全问题描述 package atguigu.java; /** * * 例子:创建三个窗口卖票,总票数为100张.使用继承Thread类的方式 * * 由于共享了ticket变量,结果会出现卖重票和错误票的问题,也就是存在线程的安全问题,待解决。 * */ class Window extends Thread{ private static int ticket = 100; //ticket 是静态变量,说明线程共享这个变量 @Override public void run() { while(true){ if(ticket > 0){ System.out.println(getName() + ":卖票,票号为:" + ticket); ticket--; }else{ break; } } } } public class WindowTest { public static void main(String[] args) { Window t1 = new Window(); Window t2 = new Window(); Window

java锁优化

为君一笑 提交于 2020-01-28 21:18:53
一、锁优化的思路和方法 锁优化是指:在多线程的并发中当用到锁时,尽可能让性能有所提高。一般并发中用到锁,就是阻塞的并发,前面讲到一般并发级别分为阻塞的和非阻塞的(非阻塞的包含:无障碍的,无等待的,无锁的等等),一旦用到锁,就是阻塞的,也就是一般最糟糕的并发,因此锁优化就是在堵塞的情况下去提高性能;所以所锁的优化就是让性能尽可能提高,不管怎么提高,堵塞的也没有无锁的并发底。让锁定的障碍降到最低,锁优化并不是说就能解决锁堵塞造成的性能问题。这是做不到的。 方法如下:  减少锁持有时间  减小锁粒度  锁分离  锁粗化  锁消除 二、减少锁持有时间 举例: public synchronized void syncMethod(){ othercode1(); mutextMethod(); othercode2(); } 使用这个锁会造成其他线程进行等待,因此让锁的的持有时间减少和锁的范围,锁的零界点就会降低,其他线程就会很快获取锁,尽可能减少了冲突时间。 改进优化如下: public void syncMethod2(){ othercode1(); synchronized(this){ mutextMethod(); } othercode2(); } 三、减小锁粒度  将大对象,拆成小对象,好处是:大大增加并行度,降低锁竞争(同时偏向锁,轻量级锁成功率提高) 