synchronized和volatile关键字

一、Demo1

1、demo1

package com.hskw.demo1;/*** synchronized关键字* synchronized关键字锁定的是对象不是代码块,demo中锁的是object对象的实例* 锁定的对象有两种:1.类的实例 2.类对象(类锁)* 加synchronized关键字之后不一定能实现线程安全,具体还要看锁定的对象是否唯一。*/
public class Demo1 {private int count = 10;private Object object = new Object();public void test(){synchronized (object){count--;System.out.println(Thread.currentThread().getName() + " count = " + count);}}}

 2、demo2

package com.hskw.demo1;public class Demo2 {private int count = 10;public void test(){//synchronized(this)锁定的是当前类的实例,这里锁定的是Demo2类的实例synchronized (this){count--;System.out.println(Thread.currentThread().getName() + " count = " + count);}}}

3、demo3

package com.hskw.demo1;public class Demo3 {private int count = 10;//直接加在方法声明上,相当于是synchronized(this)public synchronized void test(){count--;System.out.println(Thread.currentThread().getName() + " count = " + count);}}

4、demo4

package com.hskw.demo1;public class Demo4 {private static int count = 10;//synchronize关键字修饰静态方法锁定的是类对象//静态方法中synchronize锁定代码块,锁定的对象不能是类的实例,只能是类的.class文件。public synchronized static void test(){count--;System.out.println(Thread.currentThread().getName() + " count = " + count);}public static void test2(){synchronized (Demo4.class){//这里不能替换成thiscount--;}}}

二、Demo2

1、demo1

package com.hskw.demo2;import java.util.concurrent.TimeUnit;/*** 锁对象的改变* 锁定某对象o,如果o的属性发生改变,不影响锁的使用* 但是如果o变成另外一个对象,则锁定的对象发生改变* 应该避免将锁定对象的引用变成另外一个对象*/
public class Demo1 {Object o = new Object();public void test(){synchronized (o) {while (true) {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName());}}}public static void main(String[] args) {Demo1 demo = new Demo1();new Thread(demo :: test, "t1").start();try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}Thread t2 = new Thread(demo :: test, "t2");demo.o = new Object();//t2能否执行?t2.start();}}

2、demo2

package com.hskw.demo2;import java.util.concurrent.TimeUnit;/*** 不要以字符串常量作为锁定的对象* 在下面,test1和test2其实锁定的是同一个对象*/
public class Demo2 {String s1 = "hello";String s2 = "hello";public void test1(){synchronized (s1) {System.out.println("t1 start...");try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t1 end...");}}public void test2(){synchronized (s2) {System.out.println("t2 start...");}}public static void main(String[] args) {Demo2 demo = new Demo2();new Thread(demo :: test1,"test1").start();new Thread(demo :: test2,"test2").start();}}

3、demo3

package com.hskw.demo2;import java.util.concurrent.TimeUnit;/*** 同步代码快中的语句越少越好* 比较test1和test2* 业务逻辑中只有count++这句需要sync,这时不应该给整个方法上锁* 采用细粒度的锁,可以使线程争用时间变短,从而提高效率*/
public class Demo3 {int count = 0;public synchronized void test1(){try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}count ++;try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}}public void test2(){try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}synchronized (this) {count ++;}try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}}}

三、Demo3

1、demo1

package com.hskw.demo3;/*** 问题就在于线程重入的问题,* 第一个线程减了个1变成9了,还没打印,第二个线程又减了个1,第三个线程又减了个1,* 这时候虽然第一个线程只减了一个1但是却打印出来一个7(这里情况是不一定的)* 可以给方法加上synchronized*/
public class Demo1 implements Runnable{private int count = 10;@Overridepublic /*synchronized*/ void run() {count--;System.out.println(Thread.currentThread().getName() + " count = " + count);}public static void main(String[] args) {Demo1 demo = new Demo1();for (int i = 0; i < 5; i++) {new Thread(demo,"THREAD" + i).start();}}}

2、demo2

package com.hskw.demo3;public class Demo2 implements Runnable{private int count = 10;@Overridepublic synchronized void run() {count--;System.out.println(Thread.currentThread().getName() + " count = " + count);}public static void main(String[] args) {for (int i = 0; i < 5; i++) {//相比较Demo1,这里是new了五个对象,每个线程对应都拿到各自的锁标记,可以同时执行。Demo2 demo = new Demo2();new Thread(demo,"THREAD" + i).start();}}}

四、Demo4

package com.hskw.demo4;//同步方法和非同步方法是否可以同时调用?可以
public class Demo{public synchronized void test1(){System.out.println(Thread.currentThread().getName() + " test1 start...");try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + " test1 end...");}public void test2(){try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + " test2");}public static void main(String[] args) {Demo demo = new Demo();new Thread(demo :: test1,"test1").start();new Thread(demo :: test2,"test2").start();}}

五、Demo5

package com.hskw.demo5;import java.util.concurrent.TimeUnit;/*** 脏读问题* 实际业务当中应该看是否允许脏读,不允许的情况下对读方法也要加锁*/
public class Demo {String name;double balance;public synchronized void set(String name,double balance){this.name = name;try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}this.balance = balance;}public /*synchronized*/ double getBalance(String name){return this.balance;}public static void main(String[] args) {Demo demo = new Demo();new Thread(()->demo.set("huaan",100.0)).start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(demo.getBalance("huaan"));//try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(demo.getBalance("huaan"));}}

六、Demo6

package com.hskw.demo6;import java.util.concurrent.TimeUnit;//一个同步方法调用另外一个同步方法,能否得到锁?可以,synchronized本身可支持重入
public class Demo {synchronized void test1(){System.out.println("test1 start.........");try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}test2();}synchronized void test2(){try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("test2 start.......");}public static void main(String[] args) {Demo demo= new Demo();demo.test1();}}

七、Demo7

package com.hskw.demo7;import java.util.concurrent.TimeUnit;//这里是重入锁的另外一种情况,继承
public class Demo {synchronized void test(){System.out.println("demo test start........");try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("demo test end........");}public static void main(String[] args) {new Demo2().test();}}class Demo2 extends Demo {@Overridesynchronized void test(){System.out.println("demo2 test start........");super.test();System.out.println("demo2 test end........");}}

八、Demo8

package com.hskw.demo8;import java.util.concurrent.TimeUnit;/*** T2线程能否执行?*/
public class Demo {int count = 0;synchronized void test(){System.out.println(Thread.currentThread().getName() + " start......");while (true) {count ++;System.out.println(Thread.currentThread().getName() + " count = " + count);try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}if (count == 5) {//碰到异常的情况,如果没有处理,会自动释放锁,所以T2可以执行。int i = 1/0;}}}public static void main(String[] args) {Demo demo11 = new Demo();Runnable r = () -> demo11.test();new Thread(r, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(r, "t2").start();}}

九、Demo9

package com.hskw.demo9;/*** volatile 关键字,使一个变量在多个线程间可见* mian,t1线程都用到一个变量,java默认是T1线程中保留一份副本,这样如果main线程修改了该变量,* t1线程未必知道** 使用volatile关键字,会让所有线程都会读到变量的修改值** 在下面的代码中,running是存在于堆内存的t对象中* 当线程t1开始运行的时候,会把running值从内存中读到t1线程的工作区,在运行过程中直接使用这个副本,* 并不会每次都去读取堆内存,这样,当主线程修改running的值之后,t1线程感知不到,所以不会停止运行** 关于这个例子  在后面会专门花时间再讲*/
public class Demo {boolean running = true;public void test(){System.out.println("test start...");while (running){}System.out.println("test end...");}public static void main(String[] args) {Demo demo = new Demo();new Thread(demo :: test,"t1").start();try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}demo.running = false;}}

十、Demo10

package com.hskw.demo10;import java.util.ArrayList;
import java.util.List;/*** 比如说第一个线程加到100了,还没往上加,另外一个线程来了,把100拿过来执行方法,* 然后第一个线程继续加到101,第二个线程也加到101,他两往回写都是101,线程不会管你加到哪儿了,* 虽然说加了2但是实际上只加了1.* volatile并不能保证多个线程共同修改running变量时所带来的不一致问题,* 也就是说volatile不能替代synchronized或者说volatile保证不了原子性*/
public class Demo {volatile int count = 0;public void test(){for (int i = 0; i < 10000; i++) {count ++;}}public static void main(String[] args) {Demo demo = new Demo();List threads = new ArrayList();for (int i = 0; i < 10; i++) {threads.add(new Thread(demo::test, "thread-" + i));}threads.forEach((o)->o.start());threads.forEach((o)->{try {o.join();} catch (Exception e) {e.printStackTrace();}});System.out.println(demo.count);}}

十一、Demo11

package com.hskw.demo11;import java.util.ArrayList;
import java.util.List;public class Demo {int count = 0;//相比较上一个例子,synchronized既保证了原子性又保证了可见性public synchronized void test(){for (int i = 0; i < 10000; i++) {count ++;}}public static void main(String[] args) {Demo demo = new Demo();List threads = new ArrayList();for (int i = 0; i < 10; i++) {threads.add(new Thread(demo::test, "thread-" + i));}threads.forEach((o)->o.start());threads.forEach((o)->{try {o.join();} catch (Exception e) {e.printStackTrace();}});System.out.println(demo.count);}}

十二、Demo12

package com.hskw.demo12;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;/*** atomicXXX* 一道面试题:多个atomic类连续调用能否构成原子性?*/
public class Demo {AtomicInteger count = new AtomicInteger(0);//比如count加到999了,这时候一个线程拿到count判断,虽然.get方法保证原子性,但是他阻止//不了其它线程也来判断,所以第一个线程还没加完,第二个线程也进来了,这时候两个线程都给count加了public void test(){for (int i = 0; i < 10000; i++) {if(count.get() < 1000){count.incrementAndGet();}}}public static void main(String[] args) {Demo demo = new Demo();List threads = new ArrayList();for (int i = 0; i < 10; i++) {threads.add(new Thread(demo::test, "thread-" + i));}threads.forEach((o)->o.start());threads.forEach((o)->{try {o.join();} catch (Exception e) {e.printStackTrace();}});System.out.println(demo.count);}}

十三、Demo13

1、Container1

package com.hskw.demo13;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;/*** 一道面试题:实现一个容器,提供两个方法,add,size* 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,* 当个数到5个时,线程2给出提示并结束线程2** 这里list在两个线程之间不保证可见性,所以线程2始终结束不了*/
public class Container1 {List lists = new ArrayList();public void add(Object o){lists.add(o);}public int size(){return lists.size();}public static void main(String[] args) {Container1 c = new Container1();new Thread(()->{for (int i = 0; i < 10; i++) {c.add(new Object());System.out.println("add " + i);try {TimeUnit.SECONDS.sleep(1);} catch (Exception e) {e.printStackTrace();}}}," t1").start();new Thread(()->{while (true) {if (c.size() == 5) {break;}}System.out.println("t2线程结束");}, "t2").start();}}

2、Container2

package com.hskw.demo13;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;/*** 一道面试题:实现一个容器,提供两个方法,add,size* 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,* 当个数到5个时,线程2给出提示并结束** 有两个问题,第一由于没有加同步,可能size等于5的时候,有另外一个线程加了一下才break,不是很精确* 第二个问题就是浪费cpu,T2线程用的是死循环*/
public class Container2 {volatile List lists = new ArrayList();public void add(Object o){lists.add(o);}public int size(){return lists.size();}public static void main(String[] args) {Container2 c = new Container2();new Thread(()->{for (int i = 0; i < 10; i++) {c.add(new Object());System.out.println("add " + i);try {TimeUnit.SECONDS.sleep(1);} catch (Exception e) {e.printStackTrace();}}}," t1").start();new Thread(()->{while (true) {if (c.size() == 5) {break;}}System.out.println("t2线程结束");}, "t2").start();}}

3、Container3

package com.hskw.demo13;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;/*** 一道面试题:实现一个容器,提供两个方法,add,size* 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,* 线程2给出提示并结束** 这里虽然T2能够及时收到消息唤醒,但是wait会释放锁,notify不会释放锁,所以T1线程结束后* T2线程才执行完成*/
public class Container3 {volatile List lists = new ArrayList();public void add(Object o){lists.add(o);}public int size(){return lists.size();}public static void main(String[] args) {Container3 c = new Container3();Object lock = new Object();new Thread(()->{synchronized (lock) {System.out.println("t2启动");if (c.size() != 5) {try {lock.wait();} catch (Exception e) {e.printStackTrace();}}System.out.println("t2结束");}}," t2").start();new Thread(()->{System.out.println("t1启动");synchronized (lock) {for (int i = 0; i < 10; i++) {c.add(new Object());System.out.println("add " + i);if (c.size() == 5) {lock.notify();//唤醒了线程但是不会释放锁}try {TimeUnit.SECONDS.sleep(1);} catch (Exception e) {e.printStackTrace();}}}}, "t1").start();}}

4、Container4

package com.hskw.demo13;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;/*** 一道面试题:实现一个容器,提供两个方法,add,size* 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,* 当个数到5个时,线程2给出提示并结束** 相比较上一个例子,这里T1里面用wait释放锁,T2能够及时结束*/
public class Container4 {volatile List lists = new ArrayList();public void add(Object o){lists.add(o);}public int size(){return lists.size();}public static void main(String[] args) {Container4 c = new Container4();Object lock = new Object();new Thread(()->{synchronized (lock) {System.out.println("t2启动");if (c.size() != 5) {try {lock.wait();} catch (Exception e) {e.printStackTrace();}}System.out.println("t2结束");lock.notify();}}," t2").start();new Thread(()->{System.out.println("t1启动");synchronized (lock) {for (int i = 0; i < 10; i++) {c.add(new Object());System.out.println("add " + i);if (c.size() == 5) {lock.notify();try {lock.wait();//要释放锁,T2才能得到锁得以执行} catch (Exception e) {e.printStackTrace();}}try {TimeUnit.SECONDS.sleep(1);} catch (Exception e) {e.printStackTrace();}}}}, "t1").start();}}

5、Container5

package com.hskw.demo13;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;/*** 一道面试题:实现一个容器,提供两个方法,add,size* 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,* 当个数到5个时,线程2给出提示并结束** CountDownLatch* 使用await和countdown方法替代wait和notify* CountDownLatch不涉及锁定,当count的值为零时当前线程继续运行* 相当于是发令枪,运动员线程调用await等待,计数到0开始运行* 当不涉及同步,只是涉及线程通信的时候,用synchronized加wait,notify就显得太重了*/
public class Container5 {volatile List lists = new ArrayList();public void add(Object o){lists.add(o);}public int size(){return lists.size();}public static void main(String[] args) {Container5 c = new Container5();CountDownLatch latch = new CountDownLatch(1);new Thread(()->{System.out.println("t2启动");if (c.size() != 5) {System.out.println(c.size()+"==============");try {latch.await();//准备} catch (Exception e) {e.printStackTrace();}System.out.println("t2结束");}}," t2").start();new Thread(()->{System.out.println("t1启动");for (int i = 0; i < 10; i++) {c.add(new Object());System.out.println("add " + i);if (c.size() == 5) {latch.countDown();}try {TimeUnit.SECONDS.sleep(1);} catch (Exception e) {e.printStackTrace();}}}, "t1").start();}}

十四、Demo14

1、Container1

package com.hskw.demo14;import java.util.LinkedList;
import java.util.concurrent.TimeUnit;/*** 面试题:写一个固定容量同步容器,拥有Put和get方法,以及getCount方法,* 能够支持两个生产者线程以及10个消费者线程的阻塞调用* wait notifyAll** 这里探究为什么大多数情况下wait和while是一起使用的,* 因为这里是有两个生产者线程并且容器容量是固定的,生产方法加了锁。* 如果容器满了,这时候第一个生产者线程拿到了锁,他会判断有没有满,如果满了就等待,在等待* 的时候会释放掉锁资源,这时候第二个生产者线程就会拿到锁,然后他也会判断是否满,因为容器是* 满了,第二个生产者线程也会等待并且释放锁,当消费者消费之后唤醒所有线程,这时候两个生产者线程* 都醒来了,因为要竞争锁资源,比如第一个生产者线程拿到了锁,他给容器又加到十了,陷入等待状态,* 锁资源释放掉,第二个生产者线程这时候拿到锁资源,他会继续执行(从上次睡眠的地方继续),如果是if* 的话,他在wait阻塞之前就已经执行了一次if,所以不会再执行,而是继续往下执行,那这时候就超过了* 容器的容量。所以为了让他再一次判断,这里使用while*/
public class Container1{private final LinkedList lists = new LinkedList<>();private final int MAX = 10;private int count = 0;public synchronized void put(T t){while (lists.size() == MAX) {//try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}lists.add(t);++count;this.notifyAll();}public synchronized T get(){T t = null;while (lists.size() == 0) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}t = lists.removeFirst();count--;this.notifyAll();return t;}public static void main(String[] args) {Container1 c = new Container1<>();for (int i = 0; i < 100; i++) {new Thread(()->{for (int j = 0; j < 5; j++) {System.out.println(c.get());}}, "c" + i).start();}try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}for (int i = 0; i < 2; i++) {new Thread(()->{for (int j = 0; j < 25; j++) {c.put(Thread.currentThread().getName() + "" + j);}}, "p" + i).start();}}}

2、Container2

package com.hskw.demo14;import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/**** 使用Lock和Condition来实现* condition就是在什么条件下怎么做* 对比上一个例子,Condition的方式可以更加精确的指定哪些线程被唤醒**/
public class Container2 {private final LinkedList lists = new LinkedList<>();private final int MAX = 10;private int count = 0;private Lock lock = new ReentrantLock();private Condition producer = lock.newCondition();private Condition consumer = lock.newCondition();public void put(T t){try {lock.lock();while (lists.size() == MAX) {producer.await();}lists.add(t);++count;consumer.signalAll();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public T get(){T t = null;try {lock.lock();while (lists.size() == 0) {consumer.await();}t = lists.removeFirst();count --;producer.signalAll();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}return t;}public static void main(String[] args) {Container2 c = new Container2<>();for (int i = 0; i < 100; i++) {new Thread(()->{for (int j = 0; j < 5; j++) {System.out.println(c.get());}}, "c" + i).start();}try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}for (int i = 0; i < 2; i++) {new Thread(()->{for (int j = 0; j < 25; j++) {c.put(Thread.currentThread().getName() + " " + j);}}, "p" + i).start();}}
}

十五、Demo15

1、RLDemo1

package com.hskw.demo15;import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class RLDemo1 {/*** reentrantlock用于替代synchronized* 使用reentrantlock可以完成同样的功能* reentrantlock必须要手动释放锁* 使用syn锁定的话如果遇到异常,jvm会自动释放锁,但是lock必须手动释放锁,* 因此经常在finally中进行锁的释放*/Lock lock = new ReentrantLock();public void test1(){try {lock.lock();//thisfor (int i = 0; i < 3; i++) {System.out.println(i);TimeUnit.SECONDS.sleep(1);}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}public void test2(){lock.lock();System.out.println("test 2...");lock.unlock();}public static void main(String[] args) {RLDemo1 rlDemo1 = new RLDemo1();new Thread(rlDemo1::test1).start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(rlDemo1::test2).start();}}

2、RLDemo2

package com.hskw.demo15;import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class RLDemo2 {Lock lock = new ReentrantLock();public void test1(){try {lock.lock();for (int i = 0; i < 2; i++) {System.out.println(i);TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}/*** 使用reentrantlock可以进行“尝试锁定”tryLock,这样无法锁定,或者在指定时间内无法锁定,* 线程可以决定是否继续等待* 可以使用tryLock进行尝试锁定,不管锁定与否,方法都将继续执行* 可以根据tryLock的返回值来判定是否锁定* 也可以指定tryLock的时间,由于tryLock(time)抛出异常,所以要注意unclock的处理,必须放到finally中*/public void test2(){boolean locked = false;try {locked = lock.tryLock(3, TimeUnit.SECONDS);System.out.println("test2...." + locked);} catch (InterruptedException e) {e.printStackTrace();} finally {if (locked) {System.out.println("test2 end");lock.unlock();}}}public static void main(String[] args) {RLDemo2 rlDemo2 = new RLDemo2();new Thread(rlDemo2::test1).start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(rlDemo2::test2).start();}}

3、RLDemo3

package com.hskw.demo15;import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;public class RLDemo3 {public static void main(String[] args) {ReentrantLock lock = new ReentrantLock();Thread t1 = new Thread(()->{try {lock.lock();System.out.println("t1 start");TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);System.out.println("t1 end");} catch (InterruptedException e) {System.out.println("interrupted!");} finally {lock.unlock();}});t1.start();Thread t2 = new Thread(()->{boolean locked = false;try {//lock.lock();//使用lockInterruptibly来锁定可以对Interrupt方法作出响应lock.lockInterruptibly();System.out.println("t2 start");TimeUnit.SECONDS.sleep(5);System.out.println("t2 end");locked = true;} catch (InterruptedException e) {System.out.println("interrupted!");} finally {if (locked){lock.unlock();}}});t2.start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}t2.interrupt();}}

4、RLDemo4

package com.hskw.demo15;import java.util.concurrent.locks.ReentrantLock;public class RLDemo4 extends Thread{//ReentrantLock可以指定是否为公平锁,true为公平,默认为falseprivate static ReentrantLock lock = new ReentrantLock(true);@Overridepublic void run() {for (int i = 0; i < 100 ; i++) {lock.lock();try {System.out.println(Thread.currentThread().getName() + "获得锁");} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}}public static void main(String[] args) {RLDemo4 rlDemo4 = new RLDemo4();Thread t1 = new Thread(rlDemo4);Thread t2 = new Thread(rlDemo4);t1.start();t2.start();}}

是你跟在我身后太久了,看不到我所看到的景象。               ———— 山鬼谣

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部