013.线程-8.同步之条件变量

8.同步之条件变量

实际案例:

013.线程-8.同步之条件变量_第1张图片

1.线程的锁机制,会造成调度任务一直调度、或者一直没有被调度。

解决方案: 使用条件变量,请看案例2

#!/usr/bin/python
# coding: utf-8
import threading
import time

tmp=0
g_lock = threading.Lock()

def func():
    global tmp
    global g_lock

    for i in range(10, 20):
        g_lock.acquire()

        tmp -= 1
        print " %s : tmp = %d " % (threading.currentThread().getName(), tmp)

        g_lock.release()


if __name__ == "__main__":
    p = threading.Thread(target=func, args=())
    p.setDaemon(True)
    p.start()

    for i in range(10):
        g_lock.acquire()

        tmp += 1
        print " %s : tmp = %d " % (threading.currentThread().getName(), tmp)

        g_lock.release()

    p.join()

结果:

 Thread-1 : tmp = -1 
 Thread-1 : tmp = -2 
 Thread-1 : tmp = -3 
 Thread-1 : tmp = -4 
 Thread-1 : tmp = -5 
 Thread-1 : tmp = -6 
 Thread-1 : tmp = -7 
 Thread-1 : tmp = -8 
 Thread-1 : tmp = -9 
 Thread-1 : tmp = -10 
 MainThread : tmp = -9 
 MainThread : tmp = -8 
 MainThread : tmp = -7 
 MainThread : tmp = -6 
 MainThread : tmp = -5 
 MainThread : tmp = -4 
 MainThread : tmp = -3 
 MainThread : tmp = -2 
 MainThread : tmp = -1 
 MainThread : tmp = 0 
[Finished in 0.0s]

条件变量

013.线程-8.同步之条件变量_第2张图片

2.条件变量机制:

(condition,有 等待wait() 和 环境notify() , 主线程有 sleep 操作,这样 CPU 切换到子线程的几率更大。)

  • acquire([timeout])/release(): 调用关联的锁的相应方法。
  • wait([timeout]): 调用这个方法将使线程进入Condition的等待池等待通知,并释放锁。使用前线程必须已获得锁定,否则将抛出异常。
  • notify(): 调用这个方法将从等待池挑选一个线程并通知,收到通知的线程将自动调用acquire()尝试获得锁定(进入锁定池);其他线程仍然在等待池中。调用这个方法不会释放锁定。使用前线程必须已获得锁定,否则将抛出异常。
  • notifyAll(): 调用这个方法将通知等待池中所有的线程,这些线程都将进入锁定池尝试获得锁定。调用这个方法不会释放锁定。使用前线程必须已获得锁定,否则将抛出异常。
#!/usr/bin/python
# coding: utf-8
import threading
import time

tmp=0
g_cond = threading.Condition()

def func():
    global tmp
    global g_cond

    print '%s acquire Lock' % threading.currentThread().getName()
    g_cond.acquire()
    time.sleep(3)

    while True:
        if(tmp >= 3):
            tmp -= 1
            print " %s : tmp = %d " % (threading.currentThread().getName(), tmp)
        else : 
            print '%s wait singnal wait up' % threading.currentThread().getName()
            g_cond.wait()
            print '%s wait up by another thread' % threading.currentThread().getName()

    g_cond.release()

if __name__ == "__main__":
    p = threading.Thread(target=func, args=())
    p.setDaemon(True)
    p.start()

    time.sleep(1)
    while True:
        g_cond.acquire()

        if(tmp >= 3):
            print '%s notify' % threading.currentThread().getName()
            g_cond.notify()
        else : 
            tmp += 1
            print " %s : tmp = %d " % (threading.currentThread().getName(), tmp)

        time.sleep(1)         
        print '%s release Lock' % threading.currentThread().getName()
        g_cond.release()
        time.sleep(1)

    p.join()

结果:

Thread-1 acquire Lock
Thread-1 wait singnal wait up
 MainThread : tmp = 1 
MainThread release Lock
 MainThread : tmp = 2 
MainThread release Lock
 MainThread : tmp = 3 
MainThread release Lock
MainThread notify
MainThread release Lock
Thread-1 wait up by another thread
 Thread-1 : tmp = 2 
Thread-1 wait singnal wait up
 MainThread : tmp = 3 
MainThread release Lock
MainThread notify
MainThread release Lock
Thread-1 wait up by another thread
 Thread-1 : tmp = 2 
Thread-1 wait singnal wait up
 MainThread : tmp = 3 
MainThread release Lock
MainThread notify
MainThread release Lock
Thread-1 wait up by another thread
 Thread-1 : tmp = 2 
Thread-1 wait singnal wait up
 MainThread : tmp = 3 
MainThread release Lock
MainThread notify
[Cancelled]

如果 主线程没有 sleep 操作(因为主线程的acquire() 和 release() 操作很近), 就会一直在主线程上,不会切换到子线程,出现以下情况:

#!/usr/bin/python
# coding: utf-8
import threading
import time

tmp=0
g_cond = threading.Condition()

def func():
    global tmp
    global g_cond

    print '%s acquire Lock' % threading.currentThread().getName()
    g_cond.acquire()
    time.sleep(3)

    while True:
        if(tmp >= 3):
            tmp -= 1
            print " %s : tmp = %d " % (threading.currentThread().getName(), tmp)
        else : 
            print '%s wait singnal wait up' % threading.currentThread().getName()
            g_cond.wait()
            print '%s wait up by another thread' % threading.currentThread().getName()

    g_cond.release()

if __name__ == "__main__":
    p = threading.Thread(target=func, args=())
    p.setDaemon(True)
    p.start()

    time.sleep(1)
    while True:
        g_cond.acquire()

        if(tmp >= 3):
            print '%s notify' % threading.currentThread().getName()
            g_cond.notify()
        else : 
            tmp += 1
            print " %s : tmp = %d " % (threading.currentThread().getName(), tmp)

        # time.sleep(1)         
        print '%s release Lock' % threading.currentThread().getName()
        g_cond.release()
        # time.sleep(1)

    p.join()

结果:

Thread-1 acquire Lock
Thread-1 wait singnal wait up
 MainThread : tmp = 1 
MainThread release Lock
 MainThread : tmp = 2 
MainThread release Lock
 MainThread : tmp = 3 
MainThread release Lock
MainThread notify
MainThread release Lock
MainThread notify
MainThread release Lock
MainThread notify
MainThread release Lock
MainThread notify
MainThread release Lock
MainThread notify
MainThread release Lock
MainThread notify
MainThread release Lock
MainThread notify

你可能感兴趣的:(013.线程-8.同步之条件变量)