java synchronized volatile,synchronized在java中的作用

  java synchronized volatile,synchronized在java中的作用

  00-1010一、基本特征二。锁定过程偏向于轻量级锁和重量级锁III。其他优化操作锁消除锁粗化IV。可调用接口

  00-1010 1.当初是乐观锁定。如果锁频繁冲突,它将被转换为悲观锁。

  2.起初,它是一种轻型锁。如果锁持有时间长,会转换成重量级锁。

  3.实现轻量级锁时的高概率自旋锁策略。

  4.这是一把不公平的锁。

  5.这是一把重入锁。

  6.不是读写锁

  

目录

JVM将同步锁分为无锁、有偏锁、轻量级锁和重量级锁。会根据情况依次升级。

 

  00-1010假设男人是锁,女人是线。如果这个线程是唯一使用这个锁的,那么这一男一女就算不领证结婚也能幸福的生活(避免高成本操作)。然而,当女伴出现时,他们也试图争夺男方。这个时候,无论领证结婚的操作多么昂贵,女方都必然要完成这个动作,让女伴放弃。

  偏向锁并不是真正的‘锁定’,它只是在对象头做一个‘偏向锁标记’来记录这个锁属于哪个线程。如果将来没有其他线程竞争这个锁,那么就不需要其他同步操作(以避免锁定和解锁的开销)。如果将来有其他线程竞争这个锁(当前锁属于哪个线程,刚刚被记录在锁对象中,所以很容易识别当前申请锁的线程是不是之前记录的那个线程),那么

  本质上,锁定偏差相当于‘延迟锁定’。如果不锁定,可以尽量避免不必要的锁定费用。但是,你还是要做好标记,不然你也说不清什么时候真的需要锁。

  偏置锁并没有真正被锁定,只是在锁的对象头中记录了一个标记(记录锁所属的线程)。如果没有其他线程参与锁竞争,那么就不会真正执行锁操作,从而减少了程序开销。一旦真正涉及到对方线程竞争,偏向锁状态就会被取消,进入轻量锁状态。

  00-1010随着其他线程进入竞争,偏向锁状态被消除,进入轻量锁状态(自适应自旋锁)。这里的轻量级锁是通过CAS实现的。

  通过CAS检查和更新内存块(比如null=线程引用)

  如果更新成功,则认为锁定成功。

  如果更新失败,则认为锁被占用,继续以自旋模式等待(不放弃CPU)。

  Spin使CPU保持空闲,这浪费了CPU资源。因此,这里的旋转不会一直继续,而是在一定时间/次数的重试后停止旋转,这称为“自适应”

  00-1010如果竞争比较激烈,旋转不能快速获得锁定状态,就会扩展成重量级锁定。这里的重量级锁指的是内核提供的互斥锁。

  执行加锁操作,首先进入内核状态。

  在内核状态下,确定当前锁是否已被占用。

  如果锁未被占用,则锁被成功锁定,并且用户模式被切换回。

  如果锁被占用,锁定将失败。此时线程进入锁的等待队列,挂起,等待被操作系统唤醒。

  经过一系列的沧桑,锁被其他线程释放,操作系统记住了挂起的线程,于是唤醒线程,试图重新获得锁。

  

一、基本特点

 

  00-1010编译器JVM确定是否可以消除锁。如果有,可以直接淘汰

  有些应用程序使用同步代码,但它不在多线程环境中(例如StringBuffer)

  string buffer sb=new string buffer();某人追加( a );某人追加( b );某人追加( c );某人追加( d );此时,每个追加调用都涉及锁定和解锁。但是,如果这段代码只在单线程中执行,这些锁定和解锁操作就没有必要了,浪费了一些资源。

  00-1010如果一个逻辑段中出现多个锁和解锁,编译器JVM会自动粗化锁。

  领导,给下属交代工作任务。

  模式1 :

  打电话,解释任务1,然后挂断。

  打电话,解释任务2,然后挂断。

  打电话,解释任务3,然后挂断。

  模式2 :

  打电话,说明任务1,任务2,任务3,挂电话。

  s="maodian">

  

四、Callable 接口

Callable 是什么

 

  Callable 是一个 interface . 相当于把线程封装了一个 "返回值". 方便程序猿借助多线程的方式计算 结果.

  Callable 和 Runnable 相对, 都是描述一个 "任务". Callable 描述的是带有返回值的任务, Runnable 描述的是不带返回值的任务.Callable 通常需要搭配 FutureTask 来使用. FutureTask 用来保存 Callable 的返回结果. 因为 Callable 往往是在另一个线程中执行的, 啥时候执行完并不确定. FutureTask 就可以负责这个等待结果出来的工作.

  代码示例: 创建线程计算 1 + 2 + 3 + ... + 1000, 不使用 Callable 版本

  

public class Text { static class Result{ public int sum = 0; public Object locker = new Object(); } public static void main(String[] args) throws InterruptedException { Result result = new Result(); Thread t = new Thread(){ @Override public void run() { int sum = 0; for (int i = 0; i <=10000; i++){ sum += i; } result.sum = sum; synchronized (result.locker){ result.locker.notify(); } } }; t.start(); synchronized (result.locker){ while (result.sum == 0){ result.locker.wait(); } } System.out.println(result.sum); }}

代码示例: 创建线程计算 1 + 2 + 3 + ... + 1000, 使用 Callable 版本

 

  

import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask; public class Text1 { public static void main(String[] args) throws ExecutionException, InterruptedException { Callable<Integer> callable = new Callable<Integer>() { @Override public Integer call() throws Exception { int sum = 0; for (int i = 0; i <=1000; i++){ sum += i; } return sum; } }; //由于Thread不能直接传一个callable实例,就需要一个辅助类来包装 FutureTask<Integer> futureTask = new FutureTask<>(callable); Thread t = new Thread(futureTask); t.start(); //尝试在主线程获取结果 //如果FutureTask中的结果还没生成。此时就会阻塞等待 //一直等到最终的线程把这个结果算出来,get返回 Integer result = futureTask.get(); System.out.println(result); }}

到此这篇关于Java 深入浅出分析Synchronized原理与Callable接口的文章就介绍到这了,更多相关Java Synchronized 内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

 

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: