• Lock和synchronized的区别


    Lock和synchronized的区别

    sychronized可重入、不可中断、非公平;Lock可重入、可中断、非公平和公平;      

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

            条件变量就是表示条件的一种变量。但是必须说明,这里的条件是没有实际含义的,仅仅是个标记而已,并且条件的含义往往通过代码来赋予其含义。条件变量都实现了java.util.concurrent.locks.Condition接口,条件变量的实例化是通过一个Lock对象上调用newCondition()方法来获取的,这样,条件就和一个锁对象绑定起来了。因此,Java中的条件变量只能和锁配合使用,来控制并发程序访问竞争资源的安全。

            条件变量Condition接口定义了等待/通知两种类型的方法,在线程调用这些方法时,需要提前获取Condition对象关联的锁(在基于wait/notify方法实现的方案中需要获取的是对象锁)。

            Condition对象是需要关联Lock对象的,经调用Lock对象的newCondition()对象创建而来,也就是说Condition的使用是需要依赖Lock对象的。
                    - await()导致当前线程等待,直到其它线程调用该Condition的signal()方法或者signalAll()方法来唤醒该线程
                     - signal()唤醒在Lock对象上等待的单个线程。如果所有线程都在该Lock对象上等待,则会选择唤醒其中一个线程。选择是任意的
                    - signalAll()唤醒在此Lock对象上等待的所有线程。只有当前线程放弃对该Lock对象的锁定后,才可以执行被唤醒的线程

    存取款轮流操作,各自5个线程,测试结果是否正确

    1. import java.util.concurrent.locks.Condition;
    2. import java.util.concurrent.locks.Lock;
    3. import java.util.concurrent.locks.ReentrantLock;
    4. public class Test2 {
    5. public static void main(String[] args) {
    6. Account a=new Account();
    7. for(int i=0;i<5;i++) {
    8. int k=i;
    9. new Thread(()->{
    10. a.cunKuan(k);
    11. }).start();
    12. new Thread(()->{
    13. a.quKuan(k);
    14. }).start();
    15. }
    16. }
    17. }
    18. class Account{
    19. private long id;
    20. private double balance;
    21. private Lock lock=new ReentrantLock();//账户锁
    22. private Condition _save=lock.newCondition();//存款条件,一个锁上可以定义无数个条件变量
    23. private Condition _draw=lock.newCondition();//取款条件
    24. /*
    25. * 存款
    26. * >lock.lock(); 获取锁
    27. * >_save.await(); // 阻塞存款操作, await后就隐示自动释放lock直到被唤醒自动获取
    28. * >_draw.signalAll();// 唤醒所有等待取款线程
    29. * lock.unlock(); // 释放锁
    30. *
    31. * 取款
    32. * > lock.lock(); // 获取锁
    33. * > _draw.await(); // 阻塞取款操作, await后就隐示自动释放lock直到被唤醒自动获取
    34. * > _save.signalAll(); // 唤醒所有存款操作
    35. * > lock.unlock(); // 释放锁
    36. */
    37. public void cunKuan(double num) {
    38. lock.lock();
    39. try {
    40. System.out.println(Thread.currentThread()+"开始存款");
    41. balance+=num;
    42. System.out.println(Thread.currentThread()+"存款结束");
    43. _save.await();
    44. _draw.signal();
    45. }catch(Exception e) {
    46. e.printStackTrace();
    47. }finally {
    48. lock.unlock();
    49. }
    50. }
    51. public void quKuan(double num) {
    52. lock.lock();
    53. try {
    54. System.out.println(Thread.currentThread()+"开始存款");
    55. balance+=num;
    56. System.out.println(Thread.currentThread()+"存款结束");
    57. _draw.await();
    58. _save.signal();
    59. }catch(Exception e) {
    60. e.printStackTrace();
    61. }finally {
    62. lock.unlock();
    63. }
    64. }
    65. }

    生产者消费者

    用sychronized和Lock接口分别实现生产者和消费者模式

    sychronized

    1. public class Basket {
    2. private volatile Object obj=null;
    3. public synchronized void produce(Object obj) {
    4. while(this.obj!=null) {
    5. try {
    6. this.wait();
    7. } catch (InterruptedException e) {
    8. e.printStackTrace();
    9. }
    10. }
    11. this.obj=obj;
    12. this.notifyAll();
    13. System.out.println("生产了一个对象:"+obj);
    14. }
    15. public synchronized void consume() {
    16. while(this.obj==null) {
    17. try {
    18. this.wait();
    19. } catch (InterruptedException e) {
    20. e.printStackTrace();
    21. }
    22. }
    23. System.out.println("消费了一个对象:"+obj);
    24. this.obj=null;
    25. this.notifyAll();
    26. }
    27. }
    1. import java.util.Date;
    2. public class Test1 {
    3. public static void main(String[] args) {
    4. Basket basket=new Basket();
    5. Thread t1=new Producer(basket);
    6. Thread t2=new Consumer(basket);
    7. t1.start();
    8. t2.start();
    9. }
    10. }
    11. class Producer extends Thread{
    12. private Basket basket;
    13. public Producer(Basket basket) {
    14. this.basket=basket;
    15. }
    16. @Override
    17. public void run() {
    18. for(int i=0;i<20;i++) {
    19. basket.produce(new Date());
    20. }
    21. }
    22. }
    23. class Consumer extends Thread{
    24. private Basket basket;
    25. public Consumer(Basket basket) {
    26. this.basket=basket;
    27. }
    28. @Override
    29. public void run() {
    30. for(int i=0;i<20;i++) {
    31. basket.consume();
    32. }
    33. }
    34. }

    Lock

    1. import java.util.concurrent.locks.Condition;
    2. import java.util.concurrent.locks.Lock;
    3. import java.util.concurrent.locks.ReentrantLock;
    4. public class Basket2 {
    5. private volatile Object data=null;
    6. private final Lock lock=new ReentrantLock();
    7. private final Condition condition=lock.newCondition();
    8. public void produce(Object data) {
    9. lock.lock();
    10. try {
    11. while(this.data!=null) {
    12. try {
    13. condition.await();
    14. } catch (InterruptedException e) {
    15. e.printStackTrace();
    16. }
    17. }
    18. this.data=data;
    19. condition.signalAll();
    20. System.out.println("生产了一个对象:"+data);
    21. }finally {
    22. lock.unlock();
    23. }
    24. }
    25. public void consume() {
    26. lock.lock();
    27. try {
    28. while(data==null) {
    29. try {
    30. condition.await();
    31. } catch (InterruptedException e) {
    32. e.printStackTrace();
    33. }
    34. }
    35. System.out.println("消费了一个对象:"+data);
    36. this.data=null;
    37. condition.signalAll();
    38. }finally {
    39. lock.unlock();
    40. }
    41. }
    42. }
    1. import java.util.Date;
    2. public class Test2 {
    3. public static void main(String[] args) {
    4. Basket2 basket=new Basket2();
    5. Thread t1=new Producer2(basket);
    6. Thread t2=new Consumer2(basket);
    7. t1.start();
    8. t2.start();
    9. }
    10. }
    11. class Producer2 extends Thread{
    12. private Basket2 basket;
    13. public Producer2(Basket2 basket) {
    14. this.basket=basket;
    15. }
    16. @Override
    17. public void run() {
    18. for(int i=0;i<20;i++) {
    19. basket.produce(new Date());
    20. }
    21. }
    22. }
    23. class Consumer2 extends Thread{
    24. private Basket2 basket;
    25. public Consumer2(Basket2 basket) {
    26. this.basket=basket;
    27. }
    28. @Override
    29. public void run() {
    30. for(int i=0;i<20;i++) {
    31. basket.consume();
    32. }
    33. }
    34. }

    使用生产者消费者模式协调执行顺序

    Lock接口

    1. import java.util.concurrent.locks.Condition;
    2. import java.util.concurrent.locks.Lock;
    3. import java.util.concurrent.locks.ReentrantLock;
    4. public class Operat {
    5. private volatile boolean left=true;
    6. private final Lock lock=new ReentrantLock();
    7. private final Condition ac=lock.newCondition();
    8. private final Condition bc=lock.newCondition();
    9. public void printA() {
    10. lock.lock();
    11. try {
    12. while(!left)
    13. try {
    14. ac.await();
    15. } catch (InterruptedException e) {
    16. e.printStackTrace();
    17. }
    18. left=false;
    19. System.out.println("A::"+Thread.currentThread());
    20. bc.signal();
    21. }finally {
    22. lock.unlock();
    23. }
    24. }
    25. public void printB() {
    26. lock.lock();
    27. try {
    28. while(left) {
    29. try {
    30. bc.await();
    31. } catch (InterruptedException e) {
    32. e.printStackTrace();
    33. }
    34. }
    35. left=true;
    36. System.out.println("B::"+Thread.currentThread());
    37. ac.signal();
    38. }finally {
    39. lock.unlock();
    40. }
    41. }
    42. }
    1. public class Test2 {
    2. public static void main(String[] args) {
    3. Operat op = new Operat();
    4. for (int k = 0; k < 5; k++) {
    5. Thread leftHandle = new Thread(() -> {
    6. for (int i = 0; i < 10; i++) {
    7. op.printA();
    8. }
    9. });
    10. Thread rightHandle = new Thread(() -> {
    11. for (int i = 0; i < 10; i++) {
    12. op.printB();
    13. }
    14. });
    15. leftHandle.start();
    16. rightHandle.start();
    17. }
    18. }
    19. }

    Synchronized

    1. public class Operation {
    2. private volatile boolean left=true;
    3. public synchronized void printA() {
    4. while(!left) {
    5. // System.out.println("A:"+Thread.currentThread()+"begin...");
    6. try {
    7. this.wait();
    8. } catch (InterruptedException e) {
    9. e.printStackTrace();
    10. }
    11. }
    12. left=false;
    13. System.out.println("A::"+Thread.currentThread());
    14. this.notifyAll();
    15. }
    16. public synchronized void printB() {
    17. while(left) {
    18. // System.out.println("B:"+Thread.currentThread()+"begin...");
    19. try {
    20. this.wait();
    21. } catch (InterruptedException e) {
    22. e.printStackTrace();
    23. }
    24. }
    25. left=true;
    26. System.out.println("B::"+Thread.currentThread());
    27. this.notifyAll();
    28. }
    29. }
    1. public class Test1 {
    2. public static void main(String[] args) {
    3. Operation op = new Operation();
    4. for (int k = 0; k < 5; k++) {
    5. Thread leftHandle = new Thread(() -> {
    6. for (int i = 0; i < 10; i++) {
    7. op.printA();
    8. }
    9. });
    10. Thread rightHandle = new Thread(() -> {
    11. for (int i = 0; i < 10; i++) {
    12. op.printB();
    13. }
    14. });
    15. leftHandle.start();
    16. rightHandle.start();
    17. }
    18. }
    19. }
  • 相关阅读:
    数据库管理-第112期 Oracle Exadata 03-网络与ILOM(20231020)
    eKuiper Newsletter 2022-08|多平台插件一键安装,使用更便捷
    Spark 离线开发框架设计与实现
    不赚钱的科大讯飞,投资价值该怎么看?
    AE动画调整
    【每日一题】买卖股票的最佳时机 IV
    代码随想录算法训练营第六十天| 739. 每日温度 496.下一个更大元素 I
    每日三题 8.16
    【浮点数的存储】
    Isaac-gym(8):Tensor API
  • 原文地址:https://blog.csdn.net/tiger_root/article/details/126651085