def test_readers(self, readers): lock = RWLock() ready = Barrier(readers + 1) done = threading.Event() reads = [0] * readers threads = [] def read(slot): ready.wait() while not done.is_set(): with lock.shared: reads[slot] += 1 try: for i in range(readers): t = start_thread(read, i) threads.append(t) ready.wait(5) time.sleep(1) finally: done.set() for t in threads: t.join() print() avg_reads, med_reads, min_reads, max_reads = stats(reads) print("reads avg=%.2f med=%d min=%d max=%d" % (avg_reads, med_reads, min_reads, max_reads))
def test_wakeup_all_blocked_readers(self): lock = RWLock() readers = 10 ready = Barrier(readers + 1) done = Barrier(readers + 1) threads = [] def slow_reader(): ready.wait(2) with lock.shared: time.sleep(0.5) done.wait(2) try: with lock.exclusive: # Start all readers for i in range(readers): t = start_thread(slow_reader) threads.append(t) # Wait until all readers are ready ready.wait(0.5) # Ensure that all readers are blocked time.sleep(0.5) # Releasing the write lock should wake up all the readers, holding # the lock for about 0.5 seconds. with self.assertNotRaises(): done.wait(2) finally: for t in threads: t.join()
def test_fairness(self, writers, readers): lock = RWLock() ready = Barrier(writers + readers + 1) done = threading.Event() reads = [0] * readers writes = [0] * writers threads = [] def read(slot): ready.wait() while not done.is_set(): with lock.shared: reads[slot] += 1 def write(slot): ready.wait() while not done.is_set(): with lock.exclusive: writes[slot] += 1 try: for i in range(readers): t = start_thread(read, i) threads.append(t) for i in range(writers): t = start_thread(write, i) threads.append(t) ready.wait(5) time.sleep(1) finally: done.set() for t in threads: t.join() print() # TODO: needed to work around bug in expandPermutations when using # decorated test methods. print("writers: %d readers: %d" % (writers, readers)) avg_writes, med_writes, min_writes, max_writes = stats(writes) print("writes avg=%.2f med=%d min=%d max=%d" % (avg_writes, med_writes, min_writes, max_writes)) avg_reads, med_reads, min_reads, max_reads = stats(reads) print("reads avg=%.2f med=%d min=%d max=%d" % (avg_reads, med_reads, min_reads, max_reads)) avg_all = stats(writes + reads)[0] self.assertAlmostEqual(avg_reads, avg_writes, delta=avg_all / 10)
def test_lock_contention(self, writers, readers): lock = RWLock() ready = Barrier(writers + readers + 1) done = threading.Event() reads = [0] * readers writes = [0] * writers threads = [] def read(slot): ready.wait() while not done.is_set(): with lock.shared: reads[slot] += 1 def write(slot): ready.wait() while not done.is_set(): with lock.exclusive: writes[slot] += 1 try: for i in range(readers): t = start_thread(read, i) threads.append(t) for i in range(writers): t = start_thread(write, i) threads.append(t) ready.wait(5) time.sleep(1) finally: done.set() for t in threads: t.join() print() print("writers: %d readers: %d" % (writers, readers)) avg_writes, med_writes, min_writes, max_writes = stats(writes) print("writes avg=%.2f med=%d min=%d max=%d" % (avg_writes, med_writes, min_writes, max_writes)) avg_reads, med_reads, min_reads, max_reads = stats(reads) print("reads avg=%.2f med=%d min=%d max=%d" % (avg_reads, med_reads, min_reads, max_reads))