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 并发的一些相关概念学习,布布扣,bubuko.com

java 并发的一些相关概念学习

上一篇:Java 学习 第一篇


下一篇:C++技巧:加载图标LoadIcon,SetIcon