zoukankan      html  css  js  c++  java
  • Java:使用synchronized和Lock对象获取对象锁

    在并发环境下,解决共享资源冲突问题时,可以考虑使用锁机制。
    1.对象的锁
    所有对象都自动含有单一的锁。
    JVM负责跟踪对象被加锁的次数。如果一个对象被解锁,其计数变为0。在任务(线程)第一次给对象加锁的时候,计数变为1。每当这个相同的任务(线程)在此对象上获得锁时,计数会递增。
    只有首先获得锁的任务(线程)才能继续获取该对象上的多个锁。
    每当任务离开一个synchronized方法,计数递减,当计数为0的时候,锁被完全释放,此时别的任务就可以使用此资源。
    2.synchronized同步块
    2.1同步到单一对象锁
    当使用同步块时,如果方法下的同步块都同步到一个对象上的锁,则所有的任务(线程)只能互斥的进入这些同步块。
    Resource1.java演示了三个线程(包括main线程)试图进入某个类的三个不同的方法的同步块中,虽然这些同步块处在不同的方法中,但由于是同步到同一个对象(当前对象 synchronized (this)),所以对它们的方法依然是互斥的。
    Resource1.java
    package com.zj.lock;
    import java.util.concurrent.TimeUnit;
     
    public class Resource1 {
        public void f() {
           // other operations should not be locked...
           System.out.println(Thread.currentThread().getName()
                  ":not synchronized in f()");
           synchronized (this) {
               for (int i = 0; i < 5; i++) {
                  System.out.println(Thread.currentThread().getName()
                         ":synchronized in f()");
                  try {
                      TimeUnit.SECONDS.sleep(3);
                  catch (InterruptedException e) {
                      e.printStackTrace();
                  }
               }
           }
        }
     
        public void g() {
           // other operations should not be locked...
           System.out.println(Thread.currentThread().getName()
                  ":not synchronized in g()");
           synchronized (this) {
               for (int i = 0; i < 5; i++) {
                  System.out.println(Thread.currentThread().getName()
                         ":synchronized in g()");
                  try {
                      TimeUnit.SECONDS.sleep(3);
                  catch (InterruptedException e) {
                      e.printStackTrace();
                  }
               }
           }
        }
     
        public void h() {
           // other operations should not be locked...
           System.out.println(Thread.currentThread().getName()
                  ":not synchronized in h()");
           synchronized (this) {
               for (int i = 0; i < 5; i++) {
                  System.out.println(Thread.currentThread().getName()
                         ":synchronized in h()");
                  try {
                      TimeUnit.SECONDS.sleep(3);
                  catch (InterruptedException e) {
                      e.printStackTrace();
                  }
               }
           }
        }
     
        public static void main(String[] args) {
           final Resource1 rs = new Resource1();
     
           new Thread() {
               public void run() {
                  rs.f();
               }
           }.start();
     
           new Thread() {
               public void run() {
                  rs.g();
               }
           }.start();
     
           rs.h();
        }
    }
    结果:
    Thread-0:not synchronized in f()
    Thread-0:synchronized in f()
    main:not synchronized in h()
    Thread-1:not synchronized in g()
    Thread-0:synchronized in f()
    Thread-0:synchronized in f()
    Thread-0:synchronized in f()
    Thread-0:synchronized in f()
    Thread-1:synchronized in g()
    Thread-1:synchronized in g()
    Thread-1:synchronized in g()
    Thread-1:synchronized in g()
    Thread-1:synchronized in g()
    main:synchronized in h()
    main:synchronized in h()
    main:synchronized in h()
    main:synchronized in h()
    main:synchronized in h()
    2.2 同步到多个对象锁
    Resource1.java演示了三个线程(包括main线程)试图进入某个类的三个不同的方法的同步块中,这些同步块处在不同的方法中,并且是同步到三个不同的对象(synchronized (this)synchronized(syncObject1)synchronized (syncObject2)),所以对它们的方法中的临界资源访问是独立的。
    Resource2.java
    package com.zj.lock;
    import java.util.concurrent.TimeUnit;
     
    public class Resource2 {
        private Object syncObject1 = new Object();
        private Object syncObject2 = new Object();
     
        public void f() {
           // other operations should not be locked...
           System.out.println(Thread.currentThread().getName()
                  ":not synchronized in f()");
           synchronized (this) {
               for (int i = 0; i < 5; i++) {
                  System.out.println(Thread.currentThread().getName()
                         ":synchronized in f()");
                  try {
                      TimeUnit.SECONDS.sleep(3);
                  catch (InterruptedException e) {
                      e.printStackTrace();
                  }
               }
           }
        }
     
        public void g() {
           // other operations should not be locked...
           System.out.println(Thread.currentThread().getName()
                  ":not synchronized in g()");
           synchronized (syncObject1) {
               for (int i = 0; i < 5; i++) {
                  System.out.println(Thread.currentThread().getName()
                         ":synchronized in g()");
                  try {
                      TimeUnit.SECONDS.sleep(3);
                  catch (InterruptedException e) {
                      e.printStackTrace();
                  }
               }
           }
        }
     
        public void h() {
           // other operations should not be locked...
           System.out.println(Thread.currentThread().getName()
                  ":not synchronized in h()");
           synchronized (syncObject2) {
               for (int i = 0; i < 5; i++) {
                  System.out.println(Thread.currentThread().getName()
                         ":synchronized in h()");
                  try {
                      TimeUnit.SECONDS.sleep(3);
                  catch (InterruptedException e) {
                      e.printStackTrace();
                  }
               }
           }
        }
     
        public static void main(String[] args) {
           final Resource2 rs = new Resource2();
     
           new Thread() {
               public void run() {
                  rs.f();
               }
           }.start();
     
           new Thread() {
               public void run() {
                  rs.g();
               }
           }.start();
     
           rs.h();
        }
    }
    结果:
    Thread-0:not synchronized in f()
    Thread-0:synchronized in f()
    main:not synchronized in h()
    main:synchronized in h()
    Thread-1:not synchronized in g()
    Thread-1:synchronized in g()
    Thread-0:synchronized in f()
    main:synchronized in h()
    Thread-1:synchronized in g()
    Thread-0:synchronized in f()
    main:synchronized in h()
    Thread-1:synchronized in g()
    Thread-0:synchronized in f()
    main:synchronized in h()
    Thread-1:synchronized in g()
    Thread-0:synchronized in f()
    main:synchronized in h()
    Thread-1:synchronized in g()
    3.Lock对象锁
    除了使用synchronized外,还可以使用Lock对象来创建临界区。Resource3.java的演示效果同Resource1.javaResource4.java的演示效果同Resource2.java
    Resource3.java
    package com.zj.lock;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
     
    public class Resource3 {
        private Lock lock = new ReentrantLock();
     
        public void f() {
           // other operations should not be locked...
           System.out.println(Thread.currentThread().getName()
                  ":not synchronized in f()");
           lock.lock();
           try {
               for (int i = 0; i < 5; i++) {
                  System.out.println(Thread.currentThread().getName()
                         ":synchronized in f()");
                  try {
                      TimeUnit.SECONDS.sleep(3);
                  catch (InterruptedException e) {
                      e.printStackTrace();
                  }
               }
           finally {
               lock.unlock();
           }
        }
     
        public void g() {
           // other operations should not be locked...
           System.out.println(Thread.currentThread().getName()
                  ":not synchronized in g()");
           lock.lock();
           try {
               for (int i = 0; i < 5; i++) {
                  System.out.println(Thread.currentThread().getName()
                         ":synchronized in g()");
                  try {
                      TimeUnit.SECONDS.sleep(3);
                  catch (InterruptedException e) {
                      e.printStackTrace();
                  }
               }
           finally {
               lock.unlock();
           }
        }
     
        public void h() {
           // other operations should not be locked...
           System.out.println(Thread.currentThread().getName()
                  ":not synchronized in h()");
           lock.lock();
           try {
               for (int i = 0; i < 5; i++) {
                  System.out.println(Thread.currentThread().getName()
                         ":synchronized in h()");
                  try {
                      TimeUnit.SECONDS.sleep(3);
                  catch (InterruptedException e) {
                      e.printStackTrace();
                  }
               }
           finally {
               lock.unlock();
           }
        }
     
        public static void main(String[] args) {
           final Resource3 rs = new Resource3();
     
           new Thread() {
               public void run() {
                  rs.f();
               }
           }.start();
     
           new Thread() {
               public void run() {
                  rs.g();
               }
           }.start();
     
           rs.h();
        }
    }
    结果:
    Thread-0:not synchronized in f()
    Thread-0:synchronized in f()
    main:not synchronized in h()
    Thread-1:not synchronized in g()
    Thread-0:synchronized in f()
    Thread-0:synchronized in f()
    Thread-0:synchronized in f()
    Thread-0:synchronized in f()
    main:synchronized in h()
    main:synchronized in h()
    main:synchronized in h()
    main:synchronized in h()
    main:synchronized in h()
    Thread-1:synchronized in g()
    Thread-1:synchronized in g()
    Thread-1:synchronized in g()
    Thread-1:synchronized in g()
    Thread-1:synchronized in g()
    Resource4.java
    package com.zj.lock;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
     
    public class Resource4 {
        private Lock lock1 = new ReentrantLock();
        private Lock lock2 = new ReentrantLock();
        private Lock lock3 = new ReentrantLock();
     
        public void f() {
           // other operations should not be locked...
           System.out.println(Thread.currentThread().getName()
                  ":not synchronized in f()");
           lock1.lock();
           try {
               for (int i = 0; i < 5; i++) {
                  System.out.println(Thread.currentThread().getName()
                         ":synchronized in f()");
                  try {
                      TimeUnit.SECONDS.sleep(3);
                  catch (InterruptedException e) {
                      e.printStackTrace();
                  }
               }
           finally {
               lock1.unlock();
           }
        }
     
        public void g() {
           // other operations should not be locked...
           System.out.println(Thread.currentThread().getName()
                  ":not synchronized in g()");
           lock2.lock();
           try {
               for (int i = 0; i < 5; i++) {
                  System.out.println(Thread.currentThread().getName()
                         ":synchronized in g()");
                  try {
                      TimeUnit.SECONDS.sleep(3);
                  catch (InterruptedException e) {
                      e.printStackTrace();
                  }
               }
           finally {
               lock2.unlock();
           }
        }
     
        public void h() {
           // other operations should not be locked...
           System.out.println(Thread.currentThread().getName()
                  ":not synchronized in h()");
           lock3.lock();
           try {
               for (int i = 0; i < 5; i++) {
                  System.out.println(Thread.currentThread().getName()
                         ":synchronized in h()");
                  try {
                      TimeUnit.SECONDS.sleep(3);
                  catch (InterruptedException e) {
                      e.printStackTrace();
                  }
               }
           finally {
               lock3.unlock();
           }
        }
     
        public static void main(String[] args) {
           final Resource4 rs = new Resource4();
     
           new Thread() {
               public void run() {
                  rs.f();
               }
           }.start();
     
           new Thread() {
               public void run() {
                  rs.g();
               }
           }.start();
     
           rs.h();
        }
    }
    结果:
    Thread-0:not synchronized in f()
    Thread-0:synchronized in f()
    main:not synchronized in h()
    main:synchronized in h()
    Thread-1:not synchronized in g()
    Thread-1:synchronized in g()
    Thread-0:synchronized in f()
    main:synchronized in h()
    Thread-1:synchronized in g()
    Thread-0:synchronized in f()
    main:synchronized in h()
    Thread-1:synchronized in g()
    Thread-0:synchronized in f()
    main:synchronized in h()
    Thread-1:synchronized in g()
    Thread-0:synchronized in f()
    main:synchronized in h()
    Thread-1:synchronized in g()

    本文出自 “子 孑” 博客,请务必保留此出处http://zhangjunhd.blog.51cto.com/113473/70300

  • 相关阅读:
    mysql不停库不锁表在线主从配置
    MySQL5.7不停机不锁表主从同步实战
    另类 k8s 集群灾难恢复方法:用 master 服务器镜像恢复出新集群
    我在新西兰卖挖掘机之续篇十八------坚持的秘诀(坚持的秘诀就2条,第一是初始摩擦力要足够小(开头不能太困难,时间不能太久);第二是坚持的事情能够不断地给你提供某种真实的好处)(其实就是正反馈,加上一点点兴趣)
    分布式系统中那些不靠谱任务-CAP 到底是什么
    分布式系统架构中关于切分数据库事务的 ACID 性质的可用性与性能-BASE 理论和CAP 定理
    SSO协议-SAML和OAuth2
    领域建模
    基于 Docker 容器Net Core微服务部署 Nginx 集群架构
    消息队列和分布式锁
  • 原文地址:https://www.cnblogs.com/daichangya/p/12960119.html
Copyright © 2011-2022 走看看