synchronized

Lock的await/singal 和 Object的wait/notify 的区别

大兔子大兔子 提交于 2020-01-08 01:40:14
在使用Lock之前,我们都使用Object 的wait和notify实现同步的。举例来说,一个producer和consumer,consumer发现没有东西了,等待,produer生成东西了,唤醒。 线程consumer 线程producer synchronize(obj){ obj.wait();//没东西了,等待 } synchronize(obj){ obj.notify();//有东西了,唤醒 } 有了lock后,世道变了,现在是: lock.lock(); condition.await(); lock.unlock(); lock.lock(); condition.signal(); lock.unlock(); 为了突出区别,省略了若干细节。区别有三点: 1. lock不再用synchronize把同步代码包装起来; 2. 阻塞需要另外一个对象condition; 3. 同步和唤醒的对象是condition而不是lock,对应的方法是await和signal,而不是wait和notify。 为什么需要使用condition呢?简单一句话,lock更灵活。以前的方式只能有一个等待队列,在实际应用时可能需要多个,比如读和写。为了这个灵活性,lock将同步互斥控制和等待队列分离开来,互斥保证在某个时刻只有一个线程访问临界区(lock自己完成)

正确使用 Volatile 变量

橙三吉。 提交于 2020-01-08 00:51:21
Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized ”;与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是 synchronized 的一部分。本文介绍了几种有效使用 volatile 变量的模式,并强调了几种不适合使用 volatile 变量的情形。 锁提供了两种主要特性: 互斥(mutual exclusion) 和 可见性(visibility) 。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 —— 如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。 Volatile 变量 Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。Volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。因此,单独使用 volatile 还不足以实现计数器

多线程:synchronized代码块、synchronized方法、静态synchronized方法使用的锁

浪尽此生 提交于 2020-01-07 23:27:29
在学习多线程的过程中,很多资料都会指出synchronized代码块和synchronized方法使用的锁都是this ,静态synchronized方法使用的锁是类锁,那么从这个结论出发,如何进行逆向证明呢? 证明this锁 `` public class ThreadDemo3 { public static void main(String[] args) throws InterruptedException{ MyThread3 mt = new MyThread3(); Thread t1 = new Thread(mt, "窗口1"); Thread t2 = new Thread(mt, "窗口2"); t1.start(); Thread.sleep(40); mt.flag = false; t2.start(); }}​class MyThread3 implements Runnable { int tickets = 100; boolean flag = true; Object obj = new Object();​ public void run() { if (flag) { while (tickets > 0) { synchronized (obj) { if (tickets > 0) { try { Thread.sleep(40);

春招必备系列题:MySQL+锁+Redis+并发编程,拿下几个offer没问题

 ̄綄美尐妖づ 提交于 2020-01-07 21:27:48
已经迎来了2020年,相信对于大多数的程序员来说,最紧张的就是“春招”又要来临,马上迎来“金三银四”,现在也正是时候要开始准备了。春招,是一年中进大厂的最好时机,所以想要抓住这次机会,一定要提前做好准备工作。关于春招,最常问的系列题,今天帮你们准备了一套,带你们过关斩将,拿下几个offer没一点问题! 如果您需要我说的这些资料,加入我的java架构师训练营群( 859765394 )即可免费获取到,点击群号即可免费获取! 春招必备系列题之MySQL55题 Mysql 的技术特点是什么? Heap 表是什么? Mysql 服务器默认端口是什么? 与 Oracle 相比,Mysql 有什么优势? 如何区分 FLOAT 和 DOUBLE? 主键和候选键有什么区别? 如何使用 Unix shell 登录 Mysql? myisamchk 是用来做什么的? MyISAM Static 和 MyISAM Dynamic 有什么区别? LIKE 声明中的%和_是什么意思? ...... Mysql 如何优化 DISTINCT? 如何输入字符为十六进制数字? 如何显示前 50 行? 可以使用多少列创建索引? NOW()和 CURRENT_DATE()有什么区别? 什么样的对象可以使用 CREATE 语句创建? 面试专题: 春招必备系列之锁(乐观锁与悲观锁) 何谓悲观锁与乐观锁

Java学习之==> 多线程

末鹿安然 提交于 2020-01-07 14:13:20
一、创建线程的三种方式 第一种 public class App { public static void main(String[] args) { Thread thread = new Thread(() -> { while (true) { System.out.println("testThread"); } }); thread.start(); } } new Thread 创建线程 第二种 public class App { public static void main(String[] args) { Thread thread = new Thread(new Runnable() { @Override public void run() { while (true) { System.out.println("testThread"); } } }); thread.start(); } } new Thread 创建线程 第二种和第一种本质上是同一种方法,只不过第一种方法用的是 lambda表达式的写法。 第三种 public class App extends Thread{ public static void main(String[] args) { App app = new App(); app.run(); } @Override

多线程安全和内存模型

狂风中的少年 提交于 2020-01-07 08:42:26
同步 方法 使用 的是什么锁 ? synchronized 修饰方法使用锁是当前this锁。 synchronized 修饰静态方法使用锁是当前类的字节码文件 Threadlocal 什么是 Threadlocal ThreadLocal提高一个线程的局部变量,访问某个线程拥有自己局部变量。 当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 实现原理: ThreadLoca通过map集合 Map.put(“当前线程”,值); J ava 内存模型 共享内存模型指的就是Java内存模型(简称JMM), JMM 决定一个线程对共享变量的写入时 ,能 对另一个线程可见 。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系: 线程之间的共享变量存储在主内存( main memory )中,每个线程都有一个私有的本地内存( local memory ),本地内存中存储了该线程以读 / 写共享变量的副本 。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。 什么是 J ava 内存模型: java 内存模型 简称 jmm , 定 义了 一个线程 对 另一个 线程可见。 共享 变量存放在主内存中

Java多线程-synchronized与ReentrantLock

廉价感情. 提交于 2020-01-07 08:13:39
java中多线程非常重要,尤其在高并发的时候,多线程和线程之间的通信尤为重要。下面用一个抢车票的例子来演示多线程。 场景 现有余票100张,多个人(多个线程)来抢票。 创建多线程 库存100张票 public class Tickets { // 库存 private static int num = 100; // 买票的方法 public static int buyTicket(){ if (Tickets.num <= 0){ System.out.println("无余票"); return 0; } Tickets.num--; System.out.println("还剩" + Tickets.num); return Tickets.num; } } 买票的操作,该类要实现Runnable接口,操作放在run()方法中。也可以继承Thread类,也可以在Runnable中使用lambda表达式 加锁后,用lambda表达式试试 。 public class BuyTicket implements Runnable{ public String name = ""; public BuyTicket(String name) { this.name = name; } public void buy() { int buyTicket = Tickets

死锁------模拟两个员工去干活---用两个线程去是实现

橙三吉。 提交于 2020-01-06 22:06:31
代码: package cn.tedu.thread; public class DeadLockDemo { private static Print p=new Print(); private static Scann s=new Scann(); public static void main(String[] args) { //模拟两个员工去干活—用两个线程去是实现 Thread t1=new Thread(new Runnable() { @Override public void run() { //先打印在扫描 synchronized §{//锁住打印对象 p.print(); //休眠 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } //扫描—锁住 synchronized (s){ s.scan(); } } } }); Thread t2=new Thread(new Runnable() { @Override public void run() { //先扫描在打印 synchronized (s){ s.scan(); //休眠 try { Thread.sleep(10); } catch (InterruptedException

java面试(十七)

China☆狼群 提交于 2020-01-06 21:31:48
1、编译型代码和解释型代码的区别 特征: 解释型语言在运行程序的时候才翻译,每执行一次,要翻译一次,效率较低. 编译型就是直接编译成机型可以执行的,只翻译一次 优点: 解释型:可移植性好,只要有运行相应需要的解释环境,可以在不用的操作系统上运行,修改调试也非常方便 编译型:相比解释执行编译执行效率高,占用资源小,适合复杂程序 缺点: 解释型:一句一句执行解释,浪费计算机资源,效率低 编译型:兼容性差,编译型程序虽然源代码也可以移植,但前提是必须针对不同的系统分别进行编译. 2、Linux查看文件第n行 head -n data.txt | tail -1 nl data.txt | sed -n 'np' sed -n 'np' data.txt awk 'NR==n' filename 3、类加载过程 类加载过程分为三个主要步骤:加载,连接,初始化。 4、重载和重写 方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求

Multiple locks - Behind the scene

邮差的信 提交于 2020-01-06 14:56:10
问题 class A { Object lock1 = new Object(); Object lock2 = new Object(); List<Integer> list1 = new ArrayList<>(); List<Integer> list2 = new ArrayList<>(); void insert1() { synchronized (lock1) { list1.add(5); } } void insert2() { synchronized (lock2) { list2.add(5); } } void firing() { for (int i = 0; i < 1000000; i++) { insert1(); insert2(); } } Above is an part of code, here thread t1 calls firing() and t2 calls firing(). I used lock1 and lock2 so that both thread will not wait to release the