zoukankan      html  css  js  c++  java
  • java 并发的一些相关概念学习

             Thread

             synchronized

             volatile

             锁(Lock)

             原子性(Atomic)

             并发集合类

             Excutors

        每个java对象都有一个monitor,用来访问某段代码时避免其他对象访问这段代码。当某个monitor被一个线程占用,那么其他线程如果想访问由monitor控制的代码      则必须等待。通过synchronized实现,也可用wait notify来协作实现

        1 volatile:

             volatile的覆盖范围是变量级别的,同步代价低

             volatile通知jvm将变量放到主存而不是放到工作内存,这样各个线程就是共享这个变量,进而可以直接读取

             缺点:

                       容易出问题

                       难设计

                       存在脏数据,只保证了数据的可见性,无法保证原子性

             CPU原语CAS配合volatile使用实现同步

                       CompareAndSet实现非阻塞算法

                       CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)

             结合AtomicInteger的同步实现来学习

             非阻塞算法 (nonblocking algorithms)

                       具体参见:

                                http://blog.csdn.net/hsuxu/article/details/9467651

             CAS缺点:

                       开销大,不停地循环

                       ABA问题

           有ABA问题可以看出AutomicInteger不是严格意义上实现同步,可通过AtomicStampedReference加上版本控制来实现同,具体参见:

                       http://hustpawpaw.blog.163.com/blog/static/184228324201210811243127/

      

       2 synchronized:

             1 同步方法

                       锁定的是调用这个方法的对象 注意:对于同一个class的不同对象这种方法时不适用的

             2 同步块

                       public void method(Object obj) {

                                synchronized(obj) {

                                }

                                }

                       谁拿到obj这个的锁谁就可以执行这块代码。obj是程序员指定的锁对象,一般是用byte[] lock = new byte[0],比较经济

             3 作用于静态函数 和 class

                       synchronized放在静态函数前和synchronized锁xxxObject.class的效果是一样的,锁定的对象都是Class对象

                      

                       记得在《Effective Java》一书中看到过将 Foo.class和 P1.getClass()用于作同步锁还不一样,不能用P1.getClass()来达到锁这个Class的目的。P1指的是由Foo类产生的对象。

                       可以推断:如果一个类中定义了一个synchronized的static函数A,也定义了一个synchronized 的instance函数B,那么这个类的同一对象Obj在多线程中分别访问A和B两个方法时,

                       不会构成同步,因为它们的锁都不一样。A方法的锁是Obj这个对象,而B的锁是Obj所属的那个Class。

                      

                       这个我试了下貌似并不是这样effective说的这样

                       public class TestCAS {

                       int i = 0;

                       /**

                        * @param args

                        */

                       public static void main(String[] args) {

                                AtomicInteger inta = new AtomicInteger();

                                inta.incrementAndGet();

                                final TestCAS t = new TestCAS();

                                final Class<?> test = TestCAS.class;

                                final Class<?> test1 = t.getClass();

                                System.out.println(test == test1);

                                new Thread(new Runnable() {

                                        

                                         @Override

                                         public void run() {

                                                   t.functionA(test);

                                         }

                                }).start();

                               

                                new Thread(new Runnable() {

                                        

                                         @Override

                                         public void run() {

                                                   t.functionB(test1); 

                                         }

                                }).start();

                       }

                      

                       public void functionA(Class<?> clazz) {

                                synchronized (new TestCAS().getClass()) {

                                         while(i<100) {

                                                   System.out.println("A " + i++);

                                         }

                                        

                                }

                       }

                      

                       public void functionB(Class<?> clazz) {

                                synchronized (TestCAS.class) {

                                         while(i<100) {

                                                   System.out.println("B " + i++);

                                         }

                                }

                       }

             }

             synchronized 适用于写大于读的情况下,当读取操作多于写操作时会有性能瓶颈,因为在读的时候其他线程也可以有读取操作。引出下面的的ReadWriteLock

        3 ReadWriteLock

            

    ReadWriteLock解决了synchronized可能会导致的性能瓶颈,当写操作时,其他线程无法读取或写入数据,而当读操作时,其它线程无法写入数据,但却可以读取数据

             Java.util.concurrent.locks包中有个标准Lock接口。ReentrantLock 实现了Lock接口,它完全拥有synchronized的特性,同时还提供了新的功能:获取Lock的状态、非阻塞获取锁的方法tryLock()、可中断Lock。

             本人在这里只是简单的学习ReentrantReadWriteLock的readLock()和writeLock()方法,这两个方法就可以解决synchronized的瓶颈问题

             网上例子如下 原出处http://zk1878.iteye.com/blog/1005160

             1.public class ReadWriteLockDemo { 

             2.    static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 

             3. 

             4.    public static void main(String[] args) { 

             5.        Data data = new Data(); 

             6.        Worker t1 = new Worker(data,true); 

             7.        Worker t2 = new Worker(data,true); 

             8.        t1.start(); 

             9.        t2.start(); 

             10.    } 

             11. 

             12.    static class Worker extends Thread { 

             13.        Data data; 

             14.        boolean read; 

             15. 

             16.        public Worker(Data data, boolean read) { 

             17.            this.data = data; 

             18.            this.read = read; 

             19.        } 

             20. 

             21.        public void run() { 

             22.            if (read) 

             23.                data.get(); 

             24.            else 

             25.                data.set(); 

             26.        } 

             27.    } 

             28. 

             29.    static class Data { 

             30.        ReadWriteLock lock = new ReentrantReadWriteLock(); 

             31.        Lock read = lock.readLock(); 

             32.        Lock write = lock.writeLock(); 

             33.        public  void set() { 

             34.            write.lock(); 

             35.            System.out.println(Thread.currentThread().hashCode() 

             36.                    + " set:begin " + sdf.format(new Date())); 

             37.            try { 

             38.                Thread.sleep(5000); 

             39.                // 

             40.            } catch (Exception e) { 

             41. 

             42.            } finally { 

             43.                System.out.println(Thread.currentThread().hashCode() + " set:end " 

             44.                        + sdf.format(new Date())); 

             45.                write.unlock(); 

             46.            } 

             47.             

             48. 

             49.        } 

             50. 

             51.        public  int get() { 

             52.            read.lock(); 

             53.            System.out.println(Thread.currentThread().hashCode() 

             54.                    + " get :begin " + sdf.format(new Date())); 

             55.            try { 

             56.                Thread.sleep(5000); 

             57.                // 

             58.            } catch (Exception e) { 

             59. 

             60.            } finally { 

             61.                System.out.println(Thread.currentThread().hashCode() + " get :end " 

             62.                        + sdf.format(new Date())); 

             63.                read.unlock(); 

             64.            } 

             65.             

             66. 

             67.            return 1;  

             68.        } 

             69.    } 

             70.} 

  • 相关阅读:
    【JAVA基础】String 类
    【Java基础】ArrayList类
    【Java基础】Scanner类
    【Java基础】类--------封装
    spring boot默认访问静态资源
    spring boot整合servlet、filter、Listener等组件方式
    在web项目中搭建一个spring mvc + spring + mybatis的环境
    spring mvc注解版01
    spring mvc简单介绍xml版
    服务器和客户端的理解
  • 原文地址:https://www.cnblogs.com/Forrest-Janny/p/3668673.html
Copyright © 2011-2022 走看看