Java多线程中synchronized(同步锁),wait, notify,notifyAll的使用


synchronized(同步锁)分为两大类,n种使用场景,暂讲5种场景;

第一大类:两种使用场景:1.修饰该类的Class;2.修饰static方法,此时所有该类的对象只有一把同步锁,多个对象访问只有一个能拿到锁,其他访问该类,或者该static方法将被阻塞,只有拿到锁的对象使用完,系统重新分配使用权;

/** 
 * 在同类不同对象(new多次情况下)共用synchronized同步锁
 */
public class SynchronizedClass extends Thread{
    
    /** 
     * 1.synchronized(SynchronizedClass.class)修饰一个类,是给这个类加锁,Ta的所有对象用的是同一把锁(同步锁)
     */
    /*public void getCount(){
        synchronized(SynchronizedClass.class){
            for(int i = 0;i<5;i++){
                System.out.println(Thread.currentThread().getName()+":i="+i);
            }
        }
    }*/
    /** 
     * 2.public synchronized static void getCount(){}修饰一个静态方法,我们知道静态方法是属于类的而不属于对象的,
     * 同样的,synchronized修饰的静态方法锁定的是这个类的所有对象
     */
    public synchronized static void getCount(){
        for(int i = 0;i<5;i++){
            System.out.println(Thread.currentThread().getName()+":i="+i);
        }
    }
    
    @Override
    public void run() {
        // TODO Auto-generated method stub
         getCount();
    }


    public static void main(String[] args) {
        /**
         * 测试方法:针对第一类:new两个对象,但同步锁依然有效
         */
        new SynchronizedClass().start();
        new SynchronizedClass().start();
    }
}

第二大类:三种使用场景:1.修饰synchronized(this);2.修饰指定对象时(例如'银行账户',或者生产者和消费者模式中的'储存室');3.修饰一般方法,此三种场景都是针对同一对象而言,不可多次new,否则synchronized失去作用了;

package base.synchronize;

import java.util.LinkedList;

/** 
 * 操作同一个对象时的同步锁 synchronized
 */
public class CopyOfSynchronizedClass{
    LinkedList<String> store =new LinkedList<String>();
    /** 
     * 3.public synchronized void getCount(){}修饰一个普通方法,只是对同一个对象的同步线程有影响,new SynchronizedClass()多一个同步锁,不共用,岂不多锁的效果
     */
    /*public synchronized void getCount(){
        System.out.println("当前线程:"+Thread.currentThread().getName());
        for(int i = 0;i<5;i++){
            System.out.println(Thread.currentThread().getName()+":i="+i);
        }
    }*/
    
    /** 
     * 4.synchronized(this)修饰this同步代码块时,只是对同一个对象的同步线程有影响,其他试图访问该对象的线程将被阻塞。
     * new SynchronizedClass()多一个同步锁,不共用,岂不多锁的效果
     */
    /*public void getCount(){
        synchronized(this){
            System.out.println("当前线程:"+Thread.currentThread().getName());
            for(int i = 0;i<5;i++){
                System.out.println(Thread.currentThread().getName()+":i="+i);
            }
        }
    }*/
    
    /** 
     * 5.synchronized(store)修饰store指定对象最好的场景:取钱,存钱;或者生产者模式,只是对同一个对象的同步线程有影响,其他试图访问该对象的线程将被阻塞。
     * new SynchronizedClass()多一个同步锁,不共用,岂不多锁的效果
     */
    public void toTest(){
        //为每个对象创建一个线程,一位是内部类,所有操作的外部CopyOfSynchronizedClass的store是公共的
        new Thread(new Producer()).start();
        new Thread(new Consumer()).start();
    }
    //调用此方法,消费
    public void getCount(){
        synchronized(store){
            while(true){
                try{
                    while(store.size() == 0){
                        System.out.println("仓库无货!");
                        store.wait();//方法wait() 是无限期(一直)等待,直到其它线程调用notify或notifyAll方法唤醒当前的线程
                    }
                    String str = store.removeLast();
                    System.out.println("消费货品:"+str);
                    Thread.sleep(200);
                    store.notify();//notify()方法只唤醒一个等待(对象的)线程并使该线程开始执行。所以如果有多个线程等待一个对象,这个方法只会唤醒其中一个线程,
                                   //选择哪个线程取决于操作系统对多线程管理的实现(因为此处只有'生产者'和'消费者',你懂得);
                                   //notifyAll()方法会唤醒所有等待(对象的)线程,哪一个线程将会第一个处理或访问(加了synchronized修饰的场景)取决于操作系统的实现
                }catch(InterruptedException e){
                    System.out.println("consumer is interrupted! msg="+e.getMessage());
                }
            }
        }
    }
    int i=0;
    public void setCount(){
        synchronized(store){
            while(true){
                try{
                    while(store.size() > 3){
                        System.out.println("仓库货物已满!");
                        store.wait();
                    }
                    String str = "货物"+i;
                    store.add(str);
                    System.out.println("生产的货物:"+str);
                    Thread.sleep(200);
                    store.notify();
                    i++;
                }catch(InterruptedException e){
                    System.out.println("Producer is interrupted! msg="+e.getMessage());
                }
            }
        }
    }
    //生产者
    class Producer implements Runnable{
        @Override
        public void run() {
            setCount();
        }
        
    }
    //消费者
    class Consumer implements Runnable{
        @Override
        public void run() {
            // TODO Auto-generated method stub
            getCount();
        }
    }
    public static void main(String[] args) {
        /**
         * 第二大类:只new一个对象:synchronizedClass;所有动作都在这个对象中操作
         */
        CopyOfSynchronizedClass synchronizedClass = new CopyOfSynchronizedClass();
        synchronizedClass.toTest();
    }

}

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM