精华内容
下载资源
问答
  • synchronized关键字经常被用来做线程互斥锁,但是使用不当的话,经常达不到目的。初学者常对锁住的是对象还是类有疑问。 原理:无论是对象还是类都有唯一的锁,synchronized只是声明了函数调用时需要什么锁,每个锁...

    synchronized关键字经常被用来做线程互斥锁,但是使用不当的话,经常达不到目的。初学者常对锁住的是对象还是类有疑问。
    原理:无论是对象还是类都有唯一的锁,synchronized只是声明了函数调用时需要什么锁,每个锁同一时间只能由一个线程获取,借此实现了线程互斥。
    (1)分析对象锁
    A.synchronized修饰非静态函数
    接下来看实例:

    public enum Person {
        Alice,
        Bob;
    
        public synchronized void say() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " say hello world! " +TimeUtil.getCurrentTime());
        }
    
        public synchronized void speak() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " speak hello world! " + TimeUtil.getCurrentTime());
        }
    
        public void print() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " print hello world! " + TimeUtil.getCurrentTime());
        }
    
    }

    这是一个Person类,其中有三个函数,say()和speak()这种声明方式意味着调用该函数需要持有Person实例的对象锁,即用哪个实例调用,则需要持有哪个对象的锁。print()函数无需任何锁。

    public class ThreadA implements Runnable {
        @Override
        public void run() {
            Person.Alice.say();
        }
    }
    
    public class ThreadB implements Runnable {
        @Override
        public void run() {
            Person.Bob.say();
        }
    }
    
    public class ThreadC implements Runnable {
        @Override
        public void run() {
            Person.Alice.print();
        }
    }
    
    public static String getCurrentTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
        return sdf.format(new Date());
    }
    

    创建多个线程,然后执行函数:

    public class Main {
        public static void main(String[] args) {
            Thread threadA = new Thread(new ThreadA());
            threadA.setName("threadA");
            Thread threadB = new Thread(new ThreadB());
            threadB.setName("threadB");
            Thread threadC = new Thread(new ThreadC());
            threadC.setName("threadC");
            threadA.start();
            System.out.println("A启动了 " + TimeUtil.getCurrentTime());
            threadB.start();
            System.out.println("B启动了 " + TimeUtil.getCurrentTime());
            threadC.start();
            System.out.println("C启动了 " + TimeUtil.getCurrentTime());
        }
    }

    输出结果为:
    A启动了 20:26
    B启动了 20:26
    C启动了 20:26
    threadA say hello world! 20:28
    threadC print hello world! 24:21
    threadB say hello world! 20:28

    可以看出,用两个实例分别调用say()函数是不会出现互斥的。函数执行时,每个函数都可以拿到调用对象的锁。
    接下来我们进行改动,将ThreadB改为:

    public class ThreadB implements Runnable {
        @Override
        public void run() {
            Person.Alice.say();
        }
    }

    执行输出:
    A启动了 25:33
    B启动了 25:33
    C启动了 25:33
    threadA say hello world! 25:35
    threadC print hello world! 25:35
    threadB say hello world! 25:37
    可以明显看出线程B和A存在对象锁竞争,A持有Alice锁的时候,B等待。
    改动ThreadB为

    public class ThreadB implements Runnable {
        @Override
        public void run() {
            Person.Alice.speak();
        }
    }

    执行输出:
    A启动了 27:29
    B启动了 27:29
    C启动了 27:29
    threadA say hello world! 27:31
    threadC print hello world! 27:31
    threadB speak hello world! 27:33
    可以看出即使用Alice调用不同的函数,还是会出现等待.
    总结:对象锁同一时间只能由一个线程持有,此时其余线程无法再用此对象调用需要此对象锁的函数。
    B.synchronized修饰代码块
    实例如下:

    public enum Person {
        Alice,
        Bob;
    
        public synchronized void say() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " say hello world! " + TimeUtil.getCurrentTime());
        }
    
        public void speak() {
            synchronized (Alice) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " speak hello world! " + TimeUtil.getCurrentTime());
            }
        }
    }
    
    public class ThreadA implements Runnable {
        @Override
        public void run() {
            Person.Alice.say();
        }
    }
    
    public class ThreadB implements Runnable {
        @Override
        public void run() {
            Person.Alice.speak();
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Thread threadA = new Thread(new ThreadA());
            threadA.setName("threadA");
            Thread threadB = new Thread(new ThreadB());
            threadB.setName("threadB");
            threadA.start();
            System.out.println("A启动了 " + TimeUtil.getCurrentTime());
            threadB.start();
            System.out.println("B启动了 " + TimeUtil.getCurrentTime());
        }
    }

    执行输出:
    A启动了 35:26
    B启动了 35:26
    threadA say hello world! 35:28
    threadB speak hello world! 35:30
    可以看出A和B出现了互斥,A调用的say()函数用
    synchronized关键字修饰,所以此时A占用Alice锁,speak中的代码块用synchronized (Alice)修饰,说明同样需要Alice锁,因此互斥。
    改动speak函数:

    public void speak() {
        synchronized (Bob) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " speak hello world! " + TimeUtil.getCurrentTime());
        }
    }

    将需求锁改为Bob,执行输出:
    A启动了 38:36
    B启动了 38:36
    threadA say hello world! 38:38
    threadB speak hello world! 38:38
    可以看到互斥消失了。
    继续更改:

        public void speak() {
            synchronized (this) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " speak hello world! " + TimeUtil.getCurrentTime());
            }
        }

    这里的this指的是需要调用当前函数的对象锁,执行输出:
    A启动了 40:45
    B启动了 40:45
    threadA say hello world! 40:47
    threadB speak hello world! 40:49
    互斥又出现了,因为又在竞争Alice锁
    (2)分析类锁
    每一个类都有唯一且同一时间只能被唯一线程持有的类锁。
    实例如下:

    public enum Person {
        Alice,
        Bob;
    
        public static synchronized void say() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " say hello world! " + TimeUtil.getCurrentTime());
        }
    
        public static synchronized void speak() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " speak hello world! " + TimeUtil.getCurrentTime());
        }
    }
    
    public class ThreadA implements Runnable {
        @Override
        public void run() {
            Person.say();
        }
    }
    
    public class ThreadB implements Runnable {
        @Override
        public void run() {
            Person.speak();
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Thread threadA = new Thread(new ThreadA());
            threadA.setName("threadA");
            Thread threadB = new Thread(new ThreadB());
            threadB.setName("threadB");
            threadA.start();
            System.out.println("A启动了 " + TimeUtil.getCurrentTime());
            threadB.start();
            System.out.println("B启动了 " + TimeUtil.getCurrentTime());
        }
    }

    执行输出:
    A启动了 44:18
    B启动了 44:18
    threadA say hello world! 44:20
    threadB speak hello world! 44:22
    明显看到线程互斥。
    改动代码:

        public static void speak() {
            synchronized (Person.class) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " speak hello world! " + TimeUtil.getCurrentTime());
            }
        }

    改动speak函数,将里面的的代码用 synchronized (Person.class) 修饰,执行输出:
    A启动了 44:18
    B启动了 44:18
    threadA say hello world! 44:20
    threadB speak hello world! 44:22
    两个线程依旧互斥,因为还在竞争类锁。

    总结:类锁类似对象锁,唯一且同一时间只能由唯一线程持有。

    最后补充一点:类锁和对象锁是两套互斥机制,互不影响,具体看你的函数需求的是对象锁(哪个对象)还是类锁

    展开全文
  • 答案是A, synchronized关键字是同步代码块关键字, 对对象加互斥锁 详解: synchronized: 用来给对象和方法或者代码块加锁. 当它锁定一个方法或者一个代码块的时候, 同一时刻最多只有一个线程执行这个段代码 volatile:...

    A. synchronized
    B. volatile
    C. serialize
    D. static

    答案是A, synchronized关键字是同步代码块关键字, 对对象加互斥锁

    详解:

    synchronized:

    用来给对象方法或者代码块加锁. 当它锁定一个方法或者一个代码块的时候, 同一时刻最多只有一个线程执行这个段代码

    volatile:

    用来确保将变量的更新操作通知到其他线程, 当把变量声明为volatile类型后, 编译器与运行时都会注意到这个变量是共享的, 因此不会将该变量上的操作与其他内存操作一起重排序. 然而, 在访问volatile变量时, 不会执行加锁操作, 因此也就不会使执行线程阻塞, 因此, volatile变量是一种比synchronized关键字更轻量级的同步机制

    serialize:

    Java对象序列化为二进制文件

    static:

    修饰变量, 方法, 静态代码块
    静态变量:

    1. 由static修饰的变量称为静态变量

    2. 静态变量属于类, 而不属于某个类

    3. 静态变量的副本只有一个

    静态方法:

    1. 在静态方法中只能调用静态变量和静态方法
    2. 在非晶态方法中, 可以调用静态方法或者变量
    3. 在静态方法中, 可以调用静态方法或者变量
    4. 在非静态方法中, 可以调用静态方法或者变量
    5. 在静态方法中不能使用this和super关键字

    静态代码块:

    1. 用来给静态成员变量初始化
    展开全文
  • 哪个关键字可以对对象加互斥锁?() A synchronized B volatile C serialize D static synchronized的4种用法 1.方法声明时使用,放在范围操作符(public等)之后,返回类型声明(void等)之前.这时,线程获得的...

    哪个关键字可以对对象加互斥锁?()

    A synchronized
    B volatile
    C serialize
    D static

    synchronized的4种用法

    1.方法声明时使用,放在范围操作符(public等)之后,返回类型声明(void等)之前.这时,线程获得的是成员锁,即一次只能有一个线程进入该方法,其他线程要想在此时调用该方法,只能排队等候,当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入.

      public synchronized void synMethod() {
            //方法体
          }

    2.对某一代码块使用,synchronized后跟括号,括号里是变量,这样,一次只有一个线程进入该代码块.此时,线程获得的是成员锁.例如:

     public int synMethod(int a1){
            synchronized(a1) {
              //一次只能有一个线程进入
            }
          }

        3.synchronized后面括号里是一对象,此时,线程获得的是对象锁.例如:

    public class MyThread implements Runnable {
        public static void main(String args[]) {
        MyThread mt = new MyThread();
        Thread t1 = new Thread(mt, "t1");
        Thread t2 = new Thread(mt, "t2");
        Thread t3 = new Thread(mt, "t3");
        Thread t4 = new Thread(mt, "t4");
        Thread t5 = new Thread(mt, "t5");
        Thread t6 = new Thread(mt, "t6");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
        t6.start();
      }
    
      public void run() {
        synchronized (this) {
          System.out.println(Thread.currentThread().getName());
        }
      }
    } 

    对于3,如果线程进入,则得到当前对象锁,那么别的线程在该类所有对象上的任何操作都不能进行.在对象级使用锁通常是一种比较粗糙的方法。为什么要将整个对象都上锁,而不允许其他线程短暂地使用对象中其他同步方法来访问共享资源?如果一个对象拥有多个资源,就不需要只为了让一个线程使用其中一部分资源,就将所有线程都锁在外面。由于每个对象都有锁,可以如下所示使用虚拟对象来上锁:

    class FineGrainLock {
    
       MyMemberClass x, y;
       Object xlock = new Object(), ylock = new Object();
    
       public void foo() {
          synchronized(xlock) {
             //access x here
          }
    
          //do something here - but don't use shared resources
    
          synchronized(ylock) {
             //access y here
          }
       }
    
       public void bar() {
          synchronized(this) {
             //access both x and y here
          }
          //do something here - but don't use shared resources
       }
      }
    

    4.synchronized后面括号里是类,此时,线程获得的是对象锁.例如:

    class ArrayWithLockOrder{
      private static long num_locks = 0;
      private long lock_order;
      private int[] arr;
    
      public ArrayWithLockOrder(int[] a)
      {
        arr = a;
        synchronized(ArrayWithLockOrder.class) {//-----这里
          num_locks++;             // 锁数加 1。
    
          lock_order = num_locks;  // 为此对象实例设置唯一的 lock_order。
        }
      }
      public long lockOrder()
      {
        return lock_order;
      }
      public int[] array()
      {
        return arr;
      }
      }
    
      class SomeClass implements Runnable
     {
      public int sumArrays(ArrayWithLockOrder a1,
                           ArrayWithLockOrder a2)
      {
        int value = 0;
        ArrayWithLockOrder first = a1;       // 保留数组引用的一个
        ArrayWithLockOrder last = a2;        // 本地副本。
        int size = a1.array().length;
        if (size == a2.array().length)
        {
          if (a1.lockOrder() > a2.lockOrder())  // 确定并设置对象的锁定
          {                                     // 顺序。
            first = a2;
            last = a1;
          }
          synchronized(first) {              // 按正确的顺序锁定对象。
            synchronized(last) {
              int[] arr1 = a1.array();
              int[] arr2 = a2.array();
              for (int i=0; i<size; i++)
                value += arr1[i] + arr2[i];
            }
          }
        }
        return value;
    
      }
      public void run() {
        //
      }
      }
    
    

    对于4,如果线程进入,则线程在该类中所有操作不能进行,包括静态变量和静态方法,实际上,对于含有静态方法和静态变量的代码块的同步,我们通常用4来加锁.

    Volatile原理

    Java语言提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程。当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。

      在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比sychronized关键字更轻量级的同步机制。

    当对非 volatile 变量进行读写的时候,每个线程先从内存拷贝变量到CPU缓存中。如果计算机有多个CPU,每个线程可能在不同的CPU上被处理,这意味着每个线程可以拷贝到不同的 CPU cache 中。

      而声明变量是 volatile 的,JVM 保证了每次读变量都从内存中读,跳过 CPU cache 这一步。

    当一个变量定义为 volatile 之后,将具备两种特性:

      1.保证此变量对所有的线程的可见性,这里的“可见性”,如本文开头所述,当一个线程修改了这个变量的值,volatile 保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。但普通变量做不到这点,普通变量的值在线程间传递均需要通过主内存来完成。

      2.禁止指令重排序优化。有volatile修饰的变量,赋值后多执行了一个“load addl $0x0, (%esp)”操作,这个操作相当于一个内存屏障(指令重排序时不能把后面的指令重排序到内存屏障之前的位置),只有一个CPU访问内存时,并不需要内存屏障;(什么是指令重排序:是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理)。

    对象的串行化(Serialization)

    一、串行化的概念和目的
    1.什么是串行化
                对象的寿命通常随着生成该对象的程序的终止而终止。有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复。我们把对象的这种能记录自己的状态以便将来再生的能力。叫作对象的持续性(persistence)。对象通过写出描述自己状态的数值来记录自己 ,这个过程叫对象的串行化(Serialization) 。串行化的主要任务是写出对象实例变量的数值。如果交量是另一对象的引用,则引用的对象也要串行化。这个过程是递归的,串行化可能要涉及一个复杂树结构的单行化,包括原有对象、对象的对象、对象的对象的对象等等。对象所有权的层次结构称为图表(graph)。
    2.串行化的目的
                Java对象的单行化的目标是为Java的运行环境提供一组特性,如下所示:
    1)       尽量保持对象串行化的简单扼要 ,但要提供一种途径使其可根据开发者的要求进行扩展或定制。
    2)       串行化机制应严格遵守Java的对象模型 。对象的串行化状态中应该存有所有的关于种类的安全特性的信息。
    3)       对象的串行化机制应支持Java的对象持续性。
    4)       对象的串行化机制应有足够的 可扩展能力以支持对象的远程方法调用(RMI)。
    5)       对象串行化应允许对象定义自身 的格式即其自身的数据流表示形式,可外部化接口来完成这项功能。

    二、串行化方法 
                从JDK1.1开始,Java语言提供了对象串行化机制 ,在java.io包中,接口Serialization用来作为实现对象串行化的工具 ,只有实现了Serialization的类的对象才可以被串行化。
                Serializable接口中没有任何的方法。当一个类声明要实现Serializable接口时,只是表明该类参加串行化协议,而不需要实现任何特殊的方法。下面我们通过实例介绍如何对对象进行串行化。
    1.定义一个可串行化对象
                一个类,如果要使其对象可以被串行化,必须实现Serializable接口。我们定义一个类Student如下:

    
        import java.io.Serializable;   
          
        public class Student implements Serializable {   
          
            int id;// 学号   
          
            String name;// 姓名   
          
            int age;// 年龄   
          
            String department; // 系别   
          
            public Student(int id, String name, int age, String department) {   
          
                this.id = id;   
          
                this.name = name;   
          
                this.age = age;   
          
                this.department = department;   
          
            }   
          
        }  
    

    2.构造对象的输入/输出流
                要串行化一个对象,必须与一定的对象输出/输入流联系起来,通过对象输出流将对象状态保存下来,再通过对象输入流将对象状态恢复。
                java.io包中,提供了ObjectInputStream和ObjectOutputStream将数据流功能扩展至可读写对象 。在ObjectInputStream 中用readObject()方法可以直接读取一个对象,ObjectOutputStream中用writeObject()方法可以直接将对象保存到输出流中。

    
      
            FileInputStream fi = new FileInputStream("data.ser");   
      
            ObjectInputStream si = new ObjectInputStream(fi);   
      
            try {   
      
                stu = (Student) si.readObject();   
      
                si.close();   
      
            } catch (IOException e)   
      
            {   
                System.out.println(e);   
            }   
      
            System.out.println("Student Info:");   
      
            System.out.println("ID:" + stu.id);   
      
            System.out.println("Name:" + stu.name);   
      
            System.out.println("Age:" + stu.age);   
      
            System.out.println("Dep:" + stu.department);   
      
        }   
      
    }  

    运行结果

     Student Info: 
    
      ID:981036 
    
      Name:LiuMing 
    
      Age:18 
    
      Dep:CSD

     在这个例子中,我们首先定义了一个类Student,实现了Serializable接口 ,然后通过对象输出流的writeObject()方法将Student对象保存到文件 data.ser中 。之后,通过对家输入流的readObjcet()方法从文件data.ser中读出保存下来的Student对象 。从运行结果可以看到,通过串行化机制,可以正确地保存和恢复对象的状态。 

    接着我们看看别人的评论

    synchronized 关键字 : 用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这个段代码。

    volatile:用来确保将变量的跟新操作通知到其他线程,当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。然而,在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比 synchronized关键字更轻量级的同步机制。

    serialize:Java 对象序列化为二进制文件。

    static关键字: static关键字可以修饰变量,方法,静态代码块。

                              静态变量:

                                              由static修饰的变量称为静态变量

                                              静态变量属于类,而不属于某个对象

                                              静态变量它的副本只有一个(静态变量在类中只加载一)

                             静态方法:

                                              在静态方法中只能调用静态变量和静态方法

                                              在非静态方法中,可以调用静态方法或者变量。

                                              在静态方法中不能使用this和super关键字。

                            静态代码块

                                              作用:用来给静态成员变量初始化

    答案A

    文章仅个人理解,来在各大网站。如有不合理之处,欢迎吐槽。

    阅读目录(置顶)(长期更新计算机领域知识)https://blog.csdn.net/weixin_43392489/article/details/102380691

    阅读目录(置顶)(长期更新计算机领域知识)https://blog.csdn.net/weixin_43392489/article/details/102380882

    阅读目录(置顶)(长期科技领域知识)https://blog.csdn.net/weixin_43392489/article/details/102600114

    歌谣带你看java面试题 https://blog.csdn.net/weixin_43392489/article/details/102675944

    展开全文
  • 进程互斥锁

    2017-08-28 18:32:00
    互斥锁:解决的问题是,共享的资源就会有竞争,所以把加上锁,记得要解锁哦 关键字: mutex = Lock() mutex.acquire() 要加锁的程序 mutex.release() 几个互斥锁的应用! 互斥锁模拟上厕所 from ...

    互斥锁:解决的问题是,共享的资源就会有竞争,所以把加上锁,记得要解锁哦

    关键字:

    mutex = Lock()

    mutex.acquire()

    要加锁的程序

    mutex.release()

    几个互斥锁的应用!

    互斥锁模拟上厕所

    from multiprocessing import Process,Lock
    import time
    import os
    import random
    
    def func(l):
        l.acquire()
        print('%s 正在上厕所' % os.getpid())
        time.sleep(random.randint(1, 4))
        print('%s 上完厕所了' % os.getpid())
        l.release()
    
    if __name__ == '__main__':
        l = Lock()
        p1 = Process(target=func, args=(l,))
        p2 = Process(target=func, args=(l,))
        p3 = Process(target=func, args=(l,))
    
        p1.start()
        p2.start()
        p3.start()
    
        print('')

    模拟抢票

    from multiprocessing import Process,Lock
    import json
    import time
    import random
    import os
    
    #查票功能
    def search():
        dic = json.load(open('db.txt',))
        print('剩余票数%s' % dic['count'])
    
    
    #买票功能
    def get_ticket():
        dic = json.load(open('db.txt'))
        if dic['count'] > 0:
            dic['count'] -= 1
            json.dump(dic, open('db.txt', 'w'))
            print('%s 购票成功' % os.getpid())
    
    
    #模拟付款交钱所花的时间
    def task(mutex):
        search()
        time.sleep(random.randint(1, 3)) #模拟购票一系列繁琐的过程所花费的时间
    
        mutex.acquire()
        get_ticket()
        mutex.release()
    
    if __name__ == '__main__':
        mutex = Lock()
        for i in range(20):
            p = Process(target=task, args=(mutex,))
            p.start()

    队列:关键字:模块Queue

    队列:共享的,并且自带锁功能

    队列的应用:生产者消费者模型

    #生产者消费者模型2
    from multiprocessing import Process,JoinableQueue
    import time
    import random
    import os
    
    #消费者
    def consumer(q):
        while True:
            res = q.get()
            if res is None:break
            time.sleep(random.randint(1,3))
            print('\033[45m%s 吃了 %s\033[0m' % (os.getpid(), res))
            q.task_done()
    
    
    #生产者
    def product_baozi(q):
        for i in range(3):
            time.sleep(2)
            res = '包子%s' % i
            q.put(res)
            print('\033[44m%s 制造了 %s\033[0m' %(os.getpid(),res))
        q.join()
    
    
    def product_gutou(q):
        for i in range(3):
            time.sleep(2)
            res = '骨头%s' % i
            q.put(res)
            print('\033[44m%s 制造了 %s\033[0m' % (os.getpid(), res))
        q.join()
    
    
    def product_ganshui(q):
        for i in range(3):
            time.sleep(2)
            res = '泔水%s' %i
            q.put(res)
            print('\033[44m%s 制造了 %s\033[0m' % (os.getpid(), res))
        q.join()
    
    
    if __name__ == '__main__':
        q = JoinableQueue()
        #生产者们:厨师们
        p1 = Process(target=product_baozi, args=(q,))
        p2 = Process(target=product_gutou, args=(q,))
        p3 = Process(target=product_ganshui, args=(q,))
    
        #消费者们:吃货们
        p4 = Process(target=consumer, args=(q,))
        p5 = Process(target=consumer, args=(q,))
        p1.start()
        p2.start()
        p3.start()
    
        p4.daemon = True
        p5.daemon = True
        p4.start()
        p5.start()
    
        p1.join()
        p2.join()
        p3.join()
        print('')

     

    转载于:https://www.cnblogs.com/niehaidong111/p/7445246.html

    展开全文
  • 二、线程锁(也叫同步锁、互斥锁)线程锁可以在有效缩小同步范围的同时,尽可能的保证并发效率2.1 使用synchronized关键字对方法进行加锁对整个线程处理加锁(严重影响效率,不常用)2.1.1 语法public synchro...
  • 二、线程锁(也叫同步锁、互斥锁) 2.1 使用synchronized关键字对方法进行加锁 2.1.1 语法 2.1.2 案例 2.2 使用synchronize关键字对线程方法中的某一部分加锁(同步块的方式) 2.2.1 语法 2.2.2 案例 2.3 静态...
  • java.util.concurrent(JUC)包里的锁,如通过继承接口 Lock 而实现的 ReentrantLock(互斥锁),继承 ReadWriteLock 实现的 ReentrantReadWriteLock(读写锁)。 本篇主要介绍 ReentrantLock(互斥锁)。 ...
  • 并发:互斥锁

    2020-11-04 14:03:51
    为了保证某段程序的原子性,需要使得同一时刻只有一个线程执行,这就是互斥。 一段需要互斥执行的代码称之为临界区。...Java中的synchronized关键字是java在语言层面提供的互斥原语,是的一种实现。
  • C# lock 自旋锁,互斥锁,混合锁,读写锁介绍 c# 并行编程、多线程开发中,经常要用到线程锁,so, 看了许多文章,想总结一下,供自己理解记忆,以及园丁们参考使用,理解的不怎么全面,勿喷!在多线程环境中,多个...
  • 互斥锁 Synchronized

    2019-07-11 14:12:49
    使用来保护资源,首先需要确定和被保护资源的关系。...synchronized关键字,是的一种实现,可以用来修饰方法,代码块。为了确保lock() 和 unlock() 的成对出现。synchronized中内置了lock() 和 unlo...
  • Java中的“互斥锁”机制

    千次阅读 2019-01-09 22:48:24
    在Java多线程运行中为了解决共享资源时存在的多并发问题,采用“互斥锁”机制。 互斥锁:在访问共享资源之前对进行加锁操作,在访问完成之后进行解锁操作。用于保证不会出现某个线程总是竞争不过其它线程长时间不被...
  • Qt多线程:使用互斥锁

    万次阅读 2018-09-04 22:08:06
    这样每次只有一个线程可以访问它(这类似于Java synchronized关键字)。 通常最好将互斥对象与QMutexLocker一起使用,因为这样可以很容易地确保一致地执行锁定和解锁。 2、官方示例: QMutex mutex; ...
  • 互斥锁在串口通信中的简单应用

    千次阅读 2018-08-03 10:31:28
    互斥锁(英文:Mutual exclusion,常缩写为Mutex)是一种常用在多线程编程中,防止多个线程对一个公共资源做读写操作的机制,以保证共享操作的数据的完整性。互斥锁是最基本的进程或者线程间同步的方法,用来保护临界...
  • 前言 上一篇文章,我们一起学习了synchronized关键字控制的同步锁,从...ReentrantLock是一个可重入的互斥锁,又被称为“独占锁”,可重入的意思是,ReentrantLock锁可以被单个线程多次获取,“独占锁”的意思是,在...
  • Qt 使用互斥锁

    2020-03-28 22:51:07
    这样每次只有一个线程可以访问它(这类似于Java synchronized关键字)。 通常最好将互斥对象与QMutexLocker一起使用,因为这样可以很容易地确保一致地执行锁定和解锁。 2、官方示例: QMutex mutex; int number = 6;...
  • 悲观的并发策略——Synchronized互斥锁本文来自互联网,原地址作者CSDN博客作者微信synchronized关键字 volatile既然不足以保证数据同步,那么就必须要引入锁来确保。互斥锁是最常见的同步手段,在并发过程中,当多...
  • synchronize关键字互斥

    2017-11-11 21:33:44
    当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this实例)有关的。获得一个对象的也称为获取、锁定对象、在对象上锁定或在对象上同步。一个对象只有一个。所以,如果...
  • lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。 lock语句根本使用的就是Monitor.Enter和Monitor.Exit,也就是说lock(this)时执行Monitor.Enter(this),大括号结束时执行...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,375
精华内容 550
关键字:

互斥锁关键字