多线程

线程安全4 - Lock锁

2019-09-29  本文已影响0人  小超_8b2f

0. Lock就是来替换synchronized的

public class TestSynchronized {
    
    public static void main(String[] args) {
        TestSynchronized obj = new TestSynchronized();
        obj.init();
    }
    
    private void init() {
        OutPut out = new OutPut();
        new Thread() {
            @Override
            public void run() {
                while(true)
                    out.print("hello world");
            };
        }.start();
        
        new Thread() {
            @Override
            public void run() {
                while(true)
                    out.print("guchunchaoxixihaha");
            };
        }.start();
    }
    
    
    class OutPut {
        public synchronized void print(String str) {
            for(int i = 0; i < str.length(); i++) {
                System.out.print(str.charAt(i));
            }
            System.out.println();
        }
    }
}

用Lock替代写法:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {

    public static void main(String[] args) {
        TestLock obj = new TestLock();
        obj.init();
    }
    
    private void init() {
        OutPut out = new OutPut();
        new Thread() {
            @Override
            public void run() {
                while(true)
                    out.print("hello world");
            };
        }.start();
        
        new Thread() {
            @Override
            public void run() {
                while(true)
                    out.print("guchunchaoxixihaha");
            };
        }.start();
    }
    
    
    class OutPut {
        Lock lock = new ReentrantLock();
        public void print(String str) {
            lock.lock();
            try {
                for(int i = 0; i < str.length(); i++) {
                    System.out.print(str.charAt(i));
                }
                System.out.println();
            } finally {
                lock.unlock();
            }
        }
    }
}

1. 读写锁:ReentrantReadWriteLock

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLogTest {
    public static void main(String[] args) {
        final Queue3 queue = new Queue3();
        for(int i = 0; i < 3; i++) {
            new Thread(new Runnable() {  //读线程
                public void run() {
                    while(true) {
                        queue.get();
                    }
                }
            }).start();
             
            new Thread(new Runnable() { //写线程
                public void run() {
                    while(true) {
                        queue.write((int)(Math.random() * 1000));
                    }
                }
            }).start();
        }
        
    }
}


class Queue3 {
    
    //共享数据,只能有一个线程能写该数据,但可以有多个线程同时读取该数据
    private Object data = null;
    
    ReadWriteLock rwl = new ReentrantReadWriteLock();
    
    //读数据上读锁,多个读进程可同时进行,但不能喝写进程同时进行
    public void get() { 
        rwl.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " be ready to read data.");
            Thread.sleep((long)Math.random()*1000);
            System.out.println(Thread.currentThread().getName() + " have read data:" + data);
            System.out.println();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rwl.readLock().unlock();
        }
    }
    
    
    public void write(Object data) { //写数据上写锁,排他
        rwl.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " be ready to write data.");
            Thread.sleep((long)Math.random()*1000);
            this.data = data; 
            System.out.println(Thread.currentThread().getName() + " have write data:" + data);
            System.out.println();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rwl.writeLock().unlock();
        }
    }
}

2. Hibernate load()和get区别,用缓存实现代理类

User user = session.load(id,User.class); //无值则一个返回代理对象:User$Proxy
User user = session.get(id,User.class); //无值则返回null

User$Proxy extends User {
    private Integer id = id;
    
    User realUser = null;
    String getName() {
      if(realUser == null) {
        realUser = session.get(id);
        if(realUser == null) throw exception......
       return realUser.getName();
      }

    }
}

3. JAVA API ReentrantReadWriteLock 示例程序:读写锁共存

class CachedData {
   Object data;
   volatile boolean cacheValid;
   final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

   void processCachedData() {
     rwl.readLock().lock();
     if (!cacheValid) { //未被缓存过,初次赋值。上写锁,只能有一个线程写
       // Must release read lock before acquiring write lock
       rwl.readLock().unlock();
       rwl.writeLock().lock();
       try {
         // Recheck state because another thread might have
         // acquired write lock and changed state before we did.
         if (!cacheValid) {
           data = ...
           cacheValid = true;
         }
         // Downgrade by acquiring read lock before releasing write lock
         rwl.readLock().lock();
       } finally {
         rwl.writeLock().unlock(); // Unlock write, still hold read
       }
     }

     try {
       use(data); //读锁可以让多个线程同时读
     } finally {
       rwl.readLock().unlock();
     }
   }
 }
上一篇 下一篇

猜你喜欢

热点阅读