Java进阶(6) - 并发(关键字)

并发的特性
1、可见性
a、 保证任何一个线程修改变量立即写入到主内存中(堆);
b、 所有线程对该变量引用会强制立即失效,并且该线程必须去堆中获取最新的变量值。

2、指令重排序
代码的执行顺序 会在JVM中(编译器优化 指令级并行重排序 内存系统重排序 最终执行的指令序列)

3、原子性
同一时刻最多只有一个线程访问该段代码。

Volatile -> 可见性、指令重排序

Synchronied -> 可见性、指令重排序、原子性

lock
存在价值
synchronized只在以下2种情况下会释放锁
1)获取锁的线程执行完了该代码块,然后线程释放对锁的占有;
2)线程执行发生异常,此时JVM会让线程自动释放锁。
因此synchronized可能会造成线程阻塞。
为解决线程阻塞问题,引入此概念。
public interface Lock {
void lock();//获取锁,如果锁被其他线程获取,则进行等待
void lockInterruptibly() throws InterruptedException;? // tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回 false,也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。? boolean tryLock();? //tryLock(long time, TimeUnit unit)方法和tryLock()方法是类似的,只不过区别在于这个方法在拿不 到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false。如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。? boolean tryLock(long time, TimeUnit unit) throws InterruptedException;? void unlock(); //释放锁? Condition newCondition();
}

Final
final修饰的变量不可改变,在并发编程场景下性能突出。

volatile和synchronied区别
1、volatile不会造成线程的阻塞,而synchronized可能会造成线程的阻塞。(原子性差异造成)
2、volatile只能修饰变量,而synchronized则可以修饰变量和方法。
3、当一个域的值依赖于它之前的值时,volatile就无法工作了,如n=n+1,n++等。如果某个域的值受到其他域的值的限制,那么volatile也无法工作,如Range类的lower和upper边界,必须遵循lower<=upper的限制。
4、使用volatile而不是synchronized的唯一安全的情况是类中只有一个可变的域。

synchronized和lock区别
1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
5)Lock可以提高多个线程进行读操作的效率。
  在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

原文地址:https://blog.51cto.com/4397014/2436896

时间: 2024-11-09 02:00:49

Java进阶(6) - 并发(关键字)的相关文章

Java进阶(7) - 并发(多线程基本概念)

一.中断interrupt方法只改变目标线程的中断状态(interrupt status),当线程处于 wait.sleep.join等状态时都在方法内部不断地检查中断状态的值,当调用interrupt会抛出InterruptedException异常. interrupt方法Thread实例方法: 必须由其它线程获取被调用线程的实例后,进行调用.实际上,只是改变了被调用线程的内部中断状态: Thread.interrupted方法Thread类方法: 必须在当前执行线程内调用,该方法返回当前线

Java进阶(8) - 并发(多线程锁类)

一共有3类锁 ,方法锁.对象锁.类锁.(方法锁也是对象锁的一种)一.对象锁对象锁public class object {private Lock lock = new ReentrantLock();//JavaSE1.5.新增了一个java.util.concurrent包来支持同步public void method(){synchronized(this){System.out.println("我是对象锁");}}} public synchronized void meth

java进阶11 static final关键字

static表示"全局"或者"静态"的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块. 被static修饰的成员变量和成员方法独立于该类的任何对象,也就是说. 它不依赖类的特定的实例,被类的所有实例共享. package Static; public class Static { /* * 使用的情况 * 1:在对象之间共享值时 * 2:方便访问变量 * */ public static void main(String[] args){ Sta

Java 并发 关键字volatile

Java 并发 关键字volatile @author ixenos volatile只是保证了共享变量的可见性,不保证同步操作的原子性 同步块 和 volatile 关键字机制 synchronized  同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用synchronized 修饰的方法 或者 代码块. volatile 用volatile修饰的变量,线程在每次刚使用变量的时候,

Java并发关键字Volatile 详解

Java并发关键字Volatile 详解 问题引出: 1.Volatile是什么? 2.Volatile有哪些特性? 3.Volatile每个特性的底层实现原理是什么? 相关内容补充: 缓存一致性协议:MESI ? 由于计算机储存设备(硬盘等)的读写速度和CPU的计算速度有着几个数量级别的差距,为了不让CPU停下来等待读写,在CPU和存储设备之间加了高速缓存,每个CPU都有自己的高速缓存,而且他们共享同一个主内存区域,当他们都要同步到主内存时,如果每个CPU缓存里的数据都不一样,这时应该以哪个数

Java进阶(三)多线程开发关键技术

原创文章,转载请务必将下面这段话置于文章开头处. 本文转发自Jason's Blog,原文链接 http://www.jasongj.com/java/multi_thread/ sleep和wait到底什么区别 其实这个问题应该这么问--sleep和wait有什么相同点.因为这两个方法除了都能让当前线程暂停执行完,几乎没有其它相同点. wait方法是Object类的方法,这意味着所有的Java类都可以调用该方法.sleep方法是Thread类的静态方法. wait是在当前线程持有wait对象锁

Java进阶书籍推荐

学习Java,书籍是必不可少的学习工具之一,尤其是对于自学者而言.废话不多说,下边就给广大程序猿们推荐一些Java进阶的好书. 第一部分:Java语言篇 1.<Java编程规范> 适合对象:初级.中级 介绍:这本书的作者是被誉为Java之父的James Gosling,入门者推荐阅读,对基础的讲解很不错. 2.<Java编程思想> 适合对象:初级.中级 介绍:豆瓣给出了9.1的评分,全球程序员广泛赞誉.有人说这本书不适合初学者,不过小编认为作者并没有对读者已有的知识经验有过多要求,

EFFECTIVE JAVA 第十章 并发

EFFECTIVE  JAVA  第十章  并发 66.同步访问共享的可变数据 *java语言规范保证读或写一个变量是原子的(可以保证返回的值是某个线程保存在该变量中的),除非这个变量的类型为long或double.(但并不保证一个线程写入的值对于另一个线程是可见) *synchronized修饰方法.synchronized代码块可以实现同步 *volatile修饰的变量只保证读取的是主存里最新的值而不是内存中该值的拷贝,使用volatile变量必须遵循(即变量真正独立于其他变量和自己以前的值

Java基础】并发 - 多线程

Java基础]并发 - 多线程 分类: Java2014-05-03 23:56 275人阅读 评论(0) 收藏 举报 Java 目录(?)[+] 介绍 Java多线程 多线程任务执行 大多数并发应用程序时围绕执行任务(task)进行管理的:所谓任务就是抽象的,离散的工作单元. 围绕执行任务来管理应用程序时,第一步是要指明一个清晰的任务边界.大多数应用服务器程序都选择了下面这个自然的任务辩解:单独的客户请求: 任务时逻辑上的单元: 任务 Runnable 表示一个任务单元(java.lang)