zoukankan      html  css  js  c++  java
  • Java 线程同步

    Java 线程同步根本上是要符合一个逻辑:加锁------>修改------>释放锁

    1、同步代码块

    示例如下:

    public class SyncBlock {
        static class DataWrap {
            int i;
        }
        
        static class SyncBlockThread extends Thread {
            private DataWrap date;
            
            public SyncBlockThread(DataWrap dataWrap) {
                this.date = dataWrap;
            }
            
            @Override
            public void run() {
                
                for (int i = 0; i < 10; i++) {
                    synchronized (date) {
                        date.i++;
                        try {
                            sleep(1);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(getName() + " " + date.i);
                    }
                }
            }
        }
        
        public static void main(String[] args) {
            //多线程实现变量i依次加一输出
            DataWrap dataWrap = new DataWrap();
            
            new SyncBlockThread(dataWrap).start();
            new SyncBlockThread(dataWrap).start();
            new SyncBlockThread(dataWrap).start();
        }
    
    }

    示例中希望按照顺序依次输出整数。

    通常同步代码块是需要锁定的对象,一般是需要并发访问的共享资源,任何线程在修改指定资源之前都首先对该资源加锁,在加锁期间其它线程无法修改该资源。从而保证了线程的安全性。另外线程在调用sleep或者yield时并不会让出资源锁。

    2、同步方法

    public class SyncMethod {
        
        static class DataWrap{
            int i;
            
            public synchronized void valueGrow(){
                i++;
                
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " " + i);
            }
        }
        
        static class SyncMethodThread extends Thread {
            DataWrap dataWrap;
            
            public SyncMethodThread(DataWrap dataWrap){
                this.dataWrap = dataWrap;
            }
            
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    dataWrap.valueGrow();    
                }
            }
        }
        
        public static void main(String[] args) {
            //实现顺序增长并输出Datawrap中的i
            
            DataWrap dataWrap = new DataWrap();
            
            new SyncMethodThread(dataWrap).start();
            new SyncMethodThread(dataWrap).start();
            new SyncMethodThread(dataWrap).start();
        }
    
    }

    同步方法是使用synchronized关键字修饰的某个方法,同步方法锁定的就是该对象本身,所以当一个线程调用了某个对象的同步方法后,如有其它线程调用该对象的其它同步方法,也依然要等待释放该对象的锁,因为该对象已被锁定。

    3、同步锁

    通过定义同步锁对象实现同步,这种情况下,同步锁使用Lock对象充当。

    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class SyncLock {
    
        static class DataWrap{
            Lock lock = new ReentrantLock();
            int i;
            
            public void valueGrow(){
                lock.lock();
                try {
                    i++;
                    
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " " + i);    
                } finally {
                    lock.unlock();
                }
                
            }
        }
        
        static class SyncLockThread extends Thread {
            DataWrap dataWrap;
            
            public SyncLockThread(DataWrap dataWrap){
                this.dataWrap = dataWrap;
            }
            
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    dataWrap.valueGrow();    
                }
            }
        }
        
        public static void main(String[] args) {
            //实现顺序增长并输出Datawrap中的i
            
            DataWrap dataWrap = new DataWrap();
                    
            new SyncLockThread(dataWrap).start();
            new SyncLockThread(dataWrap).start();
            new SyncLockThread(dataWrap).start();
        }
    
    }

    使用锁对象实现线程同步会更灵活一些,某些锁还具有一些特定的功能,其中比较常用的ReadWriteLock读写锁,ReentrantLock可重入锁。

  • 相关阅读:
    Eclipse中jsp、js文件编辑时,卡死现象解决汇总
    环境安装备忘录 Nginx
    环境安装备忘录 Redis redis-slave-端口号.conf
    环境安装备忘录 Redis redis-common.conf
    环境安装备忘录 Redis
    Leetcode 131 Palindrome Partitioning(DFS思路)
    排序算法之快速排序(Quick Sort) -- 适用于Leetcode 75 Sort Colors
    谈STL的重要应用与实现
    二分图匹配相关问题
    理解操作系统相关知识
  • 原文地址:https://www.cnblogs.com/zj2012zy/p/5313698.html
Copyright © 2011-2022 走看看