• Nie Znaleziono Wyników

Część 2 Nie wszyscy naraz, czyli synchronizacja dla opornych

N/A
N/A
Protected

Academic year: 2021

Share "Część 2 Nie wszyscy naraz, czyli synchronizacja dla opornych"

Copied!
159
0
0

Pełen tekst

(1)

Część 2 Nie wszyscy naraz,

czyli synchronizacja dla opornych

Maciej J. Mrowiński

mrow@if.pw.edu.pl

Wydział Fizyki Politechnika Warszawska

7 grudnia 2018

(2)

Pierwszy przykład poglądowy - ucztujący filozofowie

(3)

Dzisiejszy Odcinek Sponsoruje...

(4)

Szukamy liczb pierwszych

Szukamy liczb pierwszych

(5)

Szukamy liczb pierwszych na przedziale [1, 10

10

]

1 void p r i m e P r i n t () {

2 int id = T h r e a d I D . get () ;

3 int b loc k = p owe r (10 , 9) ;

4 for(int i = ( id * b loc k ) +1; i <= ( id +1) * blo ck ; ++ i ) {

5 if( i s P r i m e ( i ) )

6 pr int ( i ) ;

7 }

8 }

(6)

Ile możemy zyskać?

Ile możemy zyskać?

(7)

Prawo Amdahla

S = 1

1 − p +

pn

(8)

Prawo Amdahla

(9)

Prawo Amdahla

(10)

Prawo Amdahla

(11)

Prawo Amdahla

S = 1

1 −

56

+

16

= 3

(12)

Prawo Amdahla

Dla n = 10 i p = 0.9 mamy

S ≈ 5

(13)

Szukamy dalej liczb pierwszych

Szukamy dalej liczb pierwszych

(14)

Wracamy do szukania liczb pierwszych

1 C o u n t e r c o u n t e r = new C o u n t e r (1) ;

2

3 void p r i m e P r i n t () {

4 long n u m b e r = 0;

5 long l imi t = p owe r (10 , 10) ;

6 wh ile( n u m b e r < li mit ) {

7 n u m b e r = c o u n t e r . g e t A n d I n c r e m e n t () ;

8 if( i s P r i m e ( i ) )

9 pr int ( i ) ;

10 }

(15)

Wracamy do szukania liczb pierwszych

1 p u b l i c cla ss C o u n t e r {

2 p r i v a t e long va lue ;

3

4 p u b l i c C o u n t e r (int i ) {

5 va lue = i ;

6 }

7

8 p u b l i c long g e t A n d I n c r e m e n t () {

9 r e t u r n val ue ++;

10 }

11 }

(16)

Wracamy do szukania liczb pierwszych

1 p u b l i c cla ss C o u n t e r {

2 p r i v a t e long va lue ;

3

4 p u b l i c C o u n t e r (int i ) {

5 va lue = i ;

6 }

7

8 p u b l i c long g e t A n d I n c r e m e n t () {

9 long temp = v alu e ;

10 va lue = temp + 1;

11 r e t u r n temp ;

12 }

(17)

Blokady (lock) i sekcje krytyczne

Blokady (lock) i sekcje krytyczne

(critical section)

(18)

Blokada

1 p u b l i c i n t e r f a c e Lock {

2 p u b l i c void lock () ;

3 p u b l i c void u n l o c k () ;

4 }

(19)

Counter z blokadą

1 p u b l i c cla ss C o u n t e r {

2 p r i v a t e long va lue ;

3 p r i v a t e Lock lock ;

4

5 p u b l i c long g e t A n d I n c r e m e n t () {

6 lock . lock () ;

7 try {

8 long temp = v alu e ;

9 va lue = temp + 1;

10 r e t u r n temp ;

11 } f i n a l l y {

12 lock . u n l o c k () ;

13 }

14 }

15 }

(20)

Co z tą blokadą?

Co z tą blokadą?

(21)

Lock - podejście 001

1 cl ass L o c k O n e i m p l e m e n t s Lock {

2 p r i v a t e b o o l e a n[] flag = new b o o l e a n[2];

3

4 p u b l i c void lock () {

5 int i = T h r e a d I D . get () ;

6 int j = 1 - i ;

7 flag [ i ] = true;

8 wh ile( flag [ j ]) ;

9 }

10

11 p u b l i c void u n l o c k () {

12 int i = T h r e a d I D . get () ;

13 flag [ i ] = f als e;

14 }

15 }

(22)

Pożądane cechy blokady

I

wzajemne wykluczanie (mutual exclusion)

I

brak zakleszczeń (deadlock)

I

brak zagłodzenia (starvation)

(23)

Lock - podejście 010

1 cl ass L o c k T w o i m p l e m e n t s Lock {

2 p r i v a t e int v i c t i m ;

3

4 p u b l i c void lock () {

5 int i = T h r e a d I D . get () ;

6 v i c t i m = i ;

7 wh ile( v i c t i m == i ) ;

8 }

9

10 p u b l i c void u n l o c k () {}

11 }

(24)

Lock - podejście 011 - algorytm Petersona

1 cl ass P e t e r s o n i m p l e m e n t s Lock {

2 p r i v a t e b o o l e a n[] flag = new b o o l e a n[2];

3 p r i v a t e int v i c t i m ;

4

5 p u b l i c void lock () {

6 int i = T h r e a d I D . get () ;

7 int j = 1 - i ;

8 flag [ i ] = true;

9 v i c t i m = i ;

10 wh ile( flag [ j ] && v i c t i m == i ) ;

11 }

12

13 p u b l i c void u n l o c k () {

14 int i = T h r e a d I D . get () ;

15 flag [ i ] = f als e;

16 }

(25)

Lock - podejście 100 - Filter Lock

1 cl ass F i l t e r i m p l e m e n t s Lock {

2 int[] l eve l ;

3 int[] v i c t i m ;

4

5 p u b l i c F i l t e r (int n ) {

6 le vel = new int[ n ];

7 v i c t i m = new int[ n ];

8 }

9

10 p u b l i c void lock () {

11 int me = T h r e a d I D . get () ;

12 for(int i = 1; i < n ; i ++) {

13 le vel [ me ] = i ;

14 v i c t i m [ i ] = me ;

15

16 wh ile(( th ere e x i s t s k != me ) ( l eve l [ k ] >= i &&

v i c t i m [ i ] == me ) ) ;

17 }

18 }

19 p u b l i c void u n l o c k () {

20 int me = T h r e a d I D . get () ;

21 le vel [ me ] = 0;

22 }

23 }

(26)

Lock - podejście 100 - Filter Lock

l = 0: n wątków l = 1: n-1 wątków l = 2: n-2 wątków

l = n - 2: 2 wątki CS: 1 wątek

(27)

Lock - podejście 101 - Bakery Lock

1 cl ass B a k e r y i m p l e m e n t s Lock {

2 b o o l e a n[] flag ;

3 La bel [] la bel;

4

5 p u b l i c B a k e r y (int n ) {

6 flag = new b o o l e a n[ n ];

7 la bel = new La bel [ n ];

8 }

9

10 p u b l i c void lock () {

11 int i = T h r e a d I D . get () ;

12 flag [ i ] = true;

13 la bel[ i ] = max (la bel[0] , ... ,la bel[n -1]) + 1;

14 wh ile (( th ere e x i s t s k != i ) ( flag [ k ] &&

15 (l abe l[ k ] , k ) << (l abe l[ i ] , i ) ) ) ;

16 }

17

18 p u b l i c void u n l o c k () {

19 flag [ T h r e a d I D . get () ] = f als e;

20 }

21 }

(28)

Przykład praktyczny

Przykład praktyczny - Singleton i

double-checked locking

(29)

Singleton

1 p u b l i c cla ss S i n g l e t o n {

2 p r i v a t e s t a t i c S i n g l e t o n s i n g l e t o n = null;

3

4 p u b l i c s t a t i c s y n c h r o n i z e d S i n g l e t o n g e t I n s t a n c e () {

5 if( s i n g l e t o n == null) {

6 s i n g l e t o n = new S i n g l e t o n () ;

7 }

8 r e t u r n s i n g l e t o n ;

9 }

10 }

(30)

Singleton

1 p u b l i c cla ss S i n g l e t o n {

2 p r i v a t e s t a t i c S i n g l e t o n s i n g l e t o n = null;

3

4 p u b l i c s t a t i c S i n g l e t o n g e t I n s t a n c e () {

5 if( s i n g l e t o n == null) {

6 s y n c h r o n i z e d( S i n g l e t o n .c las s) {

7 s i n g l e t o n = new S i n g l e t o n () ;

8 }

9 }

10 r e t u r n s i n g l e t o n ;

11 }

(31)

Singleton

1 p u b l i c cla ss S i n g l e t o n {

2 p r i v a t e s t a t i c S i n g l e t o n s i n g l e t o n = null;

3

4 p u b l i c s t a t i c S i n g l e t o n g e t I n s t a n c e () {

5 if( s i n g l e t o n == null) {

6 s y n c h r o n i z e d( S i n g l e t o n .c las s) {

7 if( s i n g l e t o n == null) {

8 s i n g l e t o n = new S i n g l e t o n () ;

9 }

10 }

11 }

12 r e t u r n s i n g l e t o n ;

13 }

14 }

(32)

Singleton

1 p u b l i c cla ss S i n g l e t o n {

2 p r i v a t e s t a t i c S i n g l e t o n s i n g l e t o n = null;

3

4 p u b l i c s t a t i c S i n g l e t o n g e t I n s t a n c e () {

5 if( s i n g l e t o n == null) {

6 s y n c h r o n i z e d( S i n g l e t o n .c las s) {

7 if( s i n g l e t o n == null) {

8 mem = a l l o c a t e () ;

9 s i n g l e t o n = mem ;

10 C o n s t r u c t o r S i n g l e t o n ( s i n g l e t o n ) ;

11 }

12 }

13 }

14 r e t u r n s i n g l e t o n ;

15 }

(33)

Singleton

1 p u b l i c cla ss S i n g l e t o n {

2 p r i v a t e s t a t i c cl ass S i n g l e t o n W r a p p e r {

3 s t a t i c S i n g l e t o n s i n g l e t o n = new S i n g l e t o n () ;

4 }

5

6 p u b l i c s t a t i c S i n g l e t o n g e t I n s t a n c e () {

7 r e t u r n S i n g l e t o n W r a p p e r . s i n g l e t o n ;

8 }

9 }

(34)

Wracamy do blokad

Wracamy do blokad

(35)

Klasy Atomic*

Klasy Atomic*

(36)

Klasy Atomic*

java.util.concurrent.atomic

I

AtomicBoolean

I

AtomicInteger

I

AtomicReference<T>

I

. . .

(37)

Klasy Atomic*

Przykład - AtomicInteger:

I

int getAndSet(int newValue)

I

int addAndGet(int delta)

I

boolean compareAndSet(int expect, int update)

I

int getAndIncrement()

I

int incrementAndGet()

(38)

Klasa ThreadLocal<T>

Klasa ThreadLocal<T>

(39)

Klasa ThreadLocal<T>

ThreadLocal<T>

I

T get()

I

protected T initialValue()

I

void set(T value)

I static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier)

(40)

Klasa ThreadLocal<T>

1 p u b l i c cla ss T h r e a d I D {

2 p r i v a t e s t a t i c fi nal A t o m i c I n t e g e r n e x t I D =

3 new A t o m i c I n t e g e r (0) ;

4

5 p r i v a t e s t a t i c fi nal T h r e a d L o c a l < Integer > t h r e a d I D =

6 T h r e a d L o c a l . w i t h I n i t i a l ( n e x t I D :: g e t A n d I n c r e m e n t ) ;

7

8 p u b l i c s t a t i c int get () {

9 r e t u r n t h r e a d I D . get () ;

10 }

(41)

Test-And-Set Lock

1 p u b l i c cla ss T A S L o c k i m p l e m e n t s Lock {

2 A t o m i c B o o l e a n sta te = new A t o m i c B o o l e a n (fal se) ;

3

4 p u b l i c void lock () {

5 wh ile( st ate . g e t A n d S e t (true) ) ;

6 }

7

8 p u b l i c void u n l o c k () {

9 st ate . set (fa lse) ;

10 }

11 }

(42)

Test-Test-And-Set Lock

1 p u b l i c cla ss T T A S L o c k i m p l e m e n t s Lock {

2 A t o m i c B o o l e a n sta te = new A t o m i c B o o l e a n (fal se) ;

3

4 p u b l i c void lock () {

5 wh ile(true) {

6 wh ile( st ate . get () ) ;

7

8 if(! sta te . g e t A n d S e t (true) )

9 r e t u r n;

10 }

11 }

12

13 p u b l i c void u n l o c k () {

14 st ate . set (fa lse) ;

15 }

(43)

Komunikacja

CPU CPU

pamięć pamięć

CPU

(44)

Backoff Lock

1 p u b l i c cla ss B a c k o f f {

2 p r i v a t e fi nal int minDelay , m a x D e l a y ;

3 p r i v a t e int li mit ;

4 p r i v a t e fi nal R a n d o m r a n d o m ;

5

6 p u b l i c B a c k o f f (int min , int max ) {

7 m i n D e l a y = min ;

8 m a x D e l a y = max ;

9 li mit = m i n D e l a y ;

10 r a n d o m = new R a n d o m () ;

11 }

12

13 p u b l i c void b a c k o f f () t h r o w s I n t e r r u p t e d E x c e p t i o n {

14 int d ela y = r a n d o m . n e x t I n t ( lim it ) ;

15 li mit = Math . min ( maxDelay , 2 * li mi t ) ;

16 T h r e a d . sle ep ( del ay ) ;

17 }

(45)

Backoff Lock

1 p u b l i c cla ss B a c k o f f L o c k i m p l e m e n t s Lock {

2 p r i v a t e A t o m i c B o o l e a n st ate = new A t o m i c B o o l e a n (f als e) ;

3 p r i v a t e s t a t i c fi nal int M I N _ D E L A Y = ...;

4 p r i v a t e s t a t i c fi nal int M A X _ D E L A Y = ...;

5

6 p u b l i c void lock () {

7 B a c k o f f b a c k o f f = new B a c k o f f ( MIN_DELAY , M A X _ D E L A Y ) ;

8 wh ile(true) {

9 wh ile( st ate . get () ) ;

10 if(! sta te . g e t A n d S e t (true) ) {

11 r e t u r n;

12 } else {

13 b a c k o f f . b a c k o f f () ;

14 }

15 }

16 }

17

18 p u b l i c void u n l o c k () {

19 st ate . set (fa lse) ;

20 }

21 }

(46)

Blokady z kolejkami

Blokady z kolejkami

(47)

Array Lock

1 p u b l i c cla ss ALo ck i m p l e m e n t s Lock {

2 T h r e a d L o c a l < Integer > m y S l o t I n d e x = new T h r e a d L o c a l < >() ; 3

4 A t o m i c I n t e g e r tail ; 5 v o l a t i l e b o o l e a n[] flag ; 6 int c a p a c i t y ;

7

8 p u b l i c ALo ck (int c a p a c i t y ) { 9 this. c a p a c i t y = c a p a c i t y ; 10 tail = new A t o m i c I n t e g e r (0) ; 11 flag = new b o o l e a n[ c a p a c i t y ];

12 flag [0] = true;

13 }

14

15 p u b l i c void lock () {

16 int slot = tail . g e t A n d I n c r e m e n t () % c a p a c i t y ; 17 m y S l o t I n d e x . set ( slot ) ;

18 wh ile(! flag [ slot ]) ;

19 }

20

21 p u b l i c void u n l o c k () {

22 int slot = m y S l o t I n d e x . get () ;

23 flag [ slot ] = f als e;

24 flag [( slot + 1) % c a p a c i t y ] = true;

25 }

26 }

(48)

CLH Lock (prawie)

1 p u b l i c cla ss C L H L o c k i m p l e m e n t s Lock { 2 p r i v a t e s t a t i c cl ass QN ode { 3 v o l a t i l e b o o l e a n l o c k e d = fal se;

4 }

5

6 A t o m i c R e f e r e n c e < QNode > tail = new A t o m i c R e f e r e n c e < >(new QNo de () ) ; 7 T h r e a d L o c a l < QNode > m y N o d e = T h r e a d L o c a l . w i t h I n i t i a l ( Q Nod e ::new) ; 8

9 p u b l i c void lock () {

10 QN ode qn ode = m y N o d e . get () ; 11 qn ode . l o c k e d = true;

12 QN ode pred = tail . g e t A n d S e t ( q nod e ) ; 13 wh ile( pred . l o c k e d ) ;

14 }

15

16 p u b l i c void u n l o c k () {

17 QN ode qn ode = m y N o d e . get () ; 18 qn ode . l o c k e d = f als e;

19 }

(49)

CLH Lock

1 p u b l i c cla ss C L H L o c k i m p l e m e n t s Lock { 2 p r i v a t e s t a t i c cl ass QN ode { 3 v o l a t i l e b o o l e a n l o c k e d = fal se;

4 }

5

6 A t o m i c R e f e r e n c e < QNode > tail = new A t o m i c R e f e r e n c e < >(new QNo de () ) ; 7 T h r e a d L o c a l < QNode > m y P r e d = new T h r e a d L o c a l < >() ;

8 T h r e a d L o c a l < QNode > m y N o d e = T h r e a d L o c a l . w i t h I n i t i a l ( Q Nod e ::new) ; 9

10 p u b l i c void lock () {

11 QN ode qn ode = m y N o d e . get () ; 12 qn ode . l o c k e d = true;

13 QN ode pred = tail . g e t A n d S e t ( q nod e ) ; 14 m y P r e d . set ( pred ) ;

15 wh ile( pred . l o c k e d ) ;

16 }

17

18 p u b l i c void u n l o c k () {

19 QN ode qn ode = m y N o d e . get () ; 20 qn ode . l o c k e d = f als e;

21 m y N o d e . set ( m y P r e d . get () ) ;

22 }

23 }

(50)

MCS Lock (prawie)

1 p u b l i c cla ss M C S L o c k i m p l e m e n t s Lock { 2 p r i v a t e s t a t i c cl ass QN ode { 3 v o l a t i l e b o o l e a n l o c k e d = fal se; 4 v o l a t i l e Q Nod e next = null;

5 }

6

7 A t o m i c R e f e r e n c e < QNode > tail = new A t o m i c R e f e r e n c e < >(null) ; 8 T h r e a d L o c a l < QNode > m y N o d e = T h r e a d L o c a l . w i t h I n i t i a l ( QN ode ::new) ; 9

10 p u b l i c void lock () {

11 QN ode qn ode = m y N o d e . get () ; 12 QN ode pred = tail . g e t A n d S e t ( q nod e ) ;

13 if( pred != null) {

14 qn ode . l o c k e d = true;

15 pred . next = q nod e ;

16 wh ile( qn ode . l o c k e d ) ;

17 }

18 }

19

20 p u b l i c void u n l o c k () { 21 QN ode qn ode = m y N o d e . get () ;

22 if( qno de . next == null)

23 r e t u r n;

24

25 qn ode . next . l o c k e d = f als e;

26 qn ode . next = null;

27 }

(51)

MCS Lock

1 p u b l i c cla ss M C S L o c k i m p l e m e n t s Lock { 2 p r i v a t e s t a t i c cl ass QN ode { 3 v o l a t i l e b o o l e a n l o c k e d = fal se; 4 v o l a t i l e Q Nod e next = null;

5 }

6

7 A t o m i c R e f e r e n c e < QNode > tail = new A t o m i c R e f e r e n c e < >(null) ; 8 T h r e a d L o c a l < QNode > m y N o d e = T h r e a d L o c a l . w i t h I n i t i a l ( QN ode ::new) ; 9

10 p u b l i c void lock () {

11 QN ode qn ode = m y N o d e . get () ; 12 QN ode pred = tail . g e t A n d S e t ( q nod e ) ;

13 if( pred != null) {

14 qn ode . l o c k e d = true;

15 pred . next = q nod e ;

16 wh ile( qn ode . l o c k e d ) ;

17 }

18 }

19

20 p u b l i c void u n l o c k () { 21 QN ode qn ode = m y N o d e . get () ;

22 if( qno de . next == null) {

23 if( tail . c o m p a r e A n d S e t ( qnode , null) )

24 r e t u r n;

25 wh ile( qn ode . next == null) ;

26 }

27 qn ode . next . l o c k e d = f als e;

28 qn ode . next = null;

29 }

30 }

(52)

Monitor

Monitor

(53)

Problem

1 mu tex . lock () ; 2 try {

3 qu eue . enq ( x ) ; 4 } f i n a l l y { 5 mu tex . u n l o c k () ; 6 }

(54)

Monitor

java.util.concurrent.locks.Lock

I

void lock()

I

void lockInterruptibly()

I

boolean tryLock()

I

boolean tryLock(long time, TimeUnit unit)

I

void unlock()

I

Condition newCondition()

(55)

Condition

java.util.concurrent.locks.Condition

I

void await()

I

boolean await(long time, TimeUnit unit)

I

long awaitNanos(long nanosTimeout)

I

void awaitUninterruptibly()

I

boolean awaitUntil(Date deadline)

I

void signal()

I

void signalAll()

(56)

Przykład - BoundedBuffer

1 cl ass B o u n d e d B u f f e r {

2 fi nal Lock lock = new R e e n t r a n t L o c k () ; 3 fi nal C o n d i t i o n n o t F u l l = lock . n e w C o n d i t i o n () ; 4 fi nal C o n d i t i o n n o t E m p t y = lock . n e w C o n d i t i o n () ; 5 fi nal O b j e c t [] it ems = new O b j e c t [ 1 0 0 ] ;

6 int putptr , takeptr , c oun t ;

7

8 p u b l i c void put ( O b j e c t x ) t h r o w s I n t e r r u p t e d E x c e p t i o n {

9 lock . lock () ;

10 try {

11 wh ile( co unt == it ems . l e n g t h ) n o t F u l l . a wai t () ;

12 it ems [ p u t p t r ] = x ;

13 if(++ p u t p t r == ite ms . l e n g t h ) p u t p t r = 0;

14 ++ cou nt ;

15 n o t E m p t y . s i g n a l () ;

16 } f i n a l l y {

17 lock . u n l o c k () ;

18 }

19 }

20 p u b l i c O b j e c t take () t h r o w s I n t e r r u p t e d E x c e p t i o n {

21 lock . lock () ;

22 try {

23 wh ile( co unt == 0) n o t E m p t y . aw ai t () ; 24 O b j e c t x = ite ms [ t a k e p t r ];

25 if(++ t a k e p t r == ite ms . l e n g t h ) t a k e p t r = 0;

26 -- c oun t ;

27 n o t F u l l . s i g n a l () ;

28 r e t u r n x ;

29 } f i n a l l y {

30 lock . u n l o c k () ;

31 }

32 }

(57)

Reentrant Lock

Reentrant Lock

(58)

Przykład - Reentrant Lock

1 p u b l i c cla ss S i m p l e R e e n t r a n t L o c k i m p l e m e n t s Lock { 2 p r i v a t e fi nal Lock lock = new S i m p l e L o c k () ;

3 p r i v a t e fi nal C o n d i t i o n c o n d i t i o n = lock . n e w C o n d i t i o n () ; 4 p r i v a t e int ow ner = 0;

5 p r i v a t e int h o l d C o u n t = 0;

(59)

Przykład - Reentrant Lock

6 p u b l i c void lock () { 7 int me = T h r e a d I D . get () ;

8 lock . lock () ;

9 try {

10 if( own er == me ) {

11 h o l d C o u n t ++;

12 r e t u r n;

13 }

14 wh ile( h o l d C o u n t != 0) c o n d i t i o n . a wai t () ; 15

16 ow ner = me ;

17 h o l d C o u n t = 1;

18 } f i n a l l y {

19 lock . u n l o c k () ;

20 }

21 }

22

23 p u b l i c void u n l o c k () {

24 lock . lock () ;

25 try {

26 if( h o l d C o u n t == 0 || own er != T h r e a d I D . get () ) 27 th row new I l l e g a l M o n i t o r S t a t e E x c e p t i o n () ;

28 holdCount - -;

29 if( h o l d C o u n t == 0)

30 c o n d i t i o n . s i g n a l () ;

31 } f i n a l l y {

32 lock . u n l o c k () ;

33 }

34 }

35 }

(60)

Readers–Writers Problem

Readers–Writers Problem

(61)

ReadWriteLock

ReadWriteLock

I

Lock readLock()

I

Lock writeLock()

(62)

ReadWriteLock

1 p u b l i c cla ss S i m p l e R e a d W r i t e L o c k i m p l e m e n t s R e a d W r i t e L o c k { 2 p r i v a t e int r e a d e r s = 0;

3 p r i v a t e b o o l e a n w r i t e r = fa lse;

4 p r i v a t e fi nal Lock lock = new R e e n t r a n t L o c k () ;

5 p r i v a t e fi nal C o n d i t i o n c o n d i t i o n = lock . n e w C o n d i t i o n () ; 6 p r i v a t e fi nal Lock r e a d L o c k = new R e a d L o c k () ;

7 p r i v a t e fi nal Lock w r i t e L o c k = new W r i t e L o c k () ; 8

9 p u b l i c Lock r e a d L o c k () { 10 r e t u r n r e a d L o c k ;

11 }

12

13 p u b l i c Lock w r i t e L o c k () { 14 r e t u r n w r i t e L o c k ;

(63)

ReadWriteLock

16 p r i v a t e cl ass R e a d L o c k i m p l e m e n t s Lock {

17 p u b l i c void lock () {

18 lock . lock () ;

19 try {

20 wh ile( w r i t e r ) c o n d i t i o n . aw ait () ;

21 r e a d e r s ++;

22 } f i n a l l y {

23 lock . u n l o c k () ;

24 }

25 }

26

27 p u b l i c void u n l o c k () {

28 lock . lock () ;

29 try {

30 readers - -;

31 if( r e a d e r s == 0)

32 c o n d i t i o n . s i g n a l A l l () ;

33 } f i n a l l y {

34 lock . u n l o c k () ;

35 }

36 }

37 }

(64)

ReadWriteLock

38 p r i v a t e cl ass W r i t e L o c k i m p l e m e n t s Lock {

39 p u b l i c void lock () {

40 lock . lock () ;

41 try {

42 wh ile( r e a d e r s > 0 || w r i t e r ) c o n d i t i o n . a wai t () ;

43 w r i t e r = true;

44 } f i n a l l y {

45 lock . u n l o c k () ;

46 }

47 }

48

49 p u b l i c void u n l o c k () {

50 lock . lock () ;

51 try {

52 w r i t e r = fal se;

53 c o n d i t i o n . s i g n a l A l l () ;

54 } f i n a l l y {

55 lock . u n l o c k () ;

56 }

57 }

58 }

(65)

ReadWriteLock

38 p r i v a t e cl ass W r i t e L o c k i m p l e m e n t s Lock {

39 p u b l i c void lock () {

40 lock . lock () ;

41 try {

42 wh ile( w r i t e r ) c o n d i t i o n . aw ait () ; 43

44 w r i t e r = true;

45 wh ile( r e a d e r s > 0) c o n d i t i o n . aw ait () ;

46 } f i n a l l y {

47 lock . u n l o c k () ;

48 }

49 }

50

51 p u b l i c void u n l o c k () {

52 w r i t e r = fal se;

53 c o n d i t i o n . s i g n a l A l l () ;

54 }

55 }

56 }

(66)

Przykład praktyczny - listy i zbiory

Przykład praktyczny - listy i zbiory

(67)

Set i Node

1 p u b l i c i n t e r f a c e Set < T > { 2 b o o l e a n add ( T x ) ; 3 b o o l e a n r e m o v e ( T x ) ; 4 b o o l e a n c o n t a i n s ( T x ) ; 5 }

6

7 p r i v a t e cl ass Node <T > { 8 v o l a t i l e T item ; 9 v o l a t i l e int key ; 10 v o l a t i l e Node next ; 11 }

(68)

Przykład praktyczny - coarse-grained

Lista - coarse-grained

(69)

CoarseList

1 p u b l i c cla ss Coa rse Lis t < T > { 2 p r i v a t e Node head ;

3 p r i v a t e Lock lock = new R e e n t r a n t L o c k () ; 4

5 p u b l i c C o a r s e L i s t () {

6 head = new Node ( I n t e g e r . M I N _ V A L U E ) ; 7 head . next = new Node ( I n t e g e r . M A X _ V A L U E ) ;

8 }

9

10 p u b l i c b o o l e a n add ( T item ) {

11 Node pred , curr ;

12 int key = item . h a s h C o d e () ;

13 lock . lock () ;

14 try {

15 pred = head ;

16 curr = pred . next ;

17 wh ile( curr . key < key ) {

18 pred = curr ;

19 curr = curr . next ;

20 }

21 if( key == curr . key ) {

22 r e t u r n fal se;

23 } else {

24 Node node = new Node ( item ) ;

25 node . next = curr ;

26 pred . next = node ;

27 r e t u r n true;

28 }

29 } f i n a l l y {

30 lock . u n l o c k () ;

31 }

32 }

(70)

CoarseList

33 p u b l i c b o o l e a n r e m o v e ( T item ) {

34 Node pred , curr ;

35 int key = item . h a s h C o d e () ;

36 lock . lock () ;

37 try {

38 pred = head ;

39 curr = pred . next ;

40 wh ile( curr . key < key ) {

41 pred = curr ;

42 curr = curr . next ;

43 }

44 if( key == curr . key ) {

45 pred . next = curr . next ;

46 r e t u r n true;

47 } else {

48 r e t u r n fal se;

49 }

50 } f i n a l l y {

51 lock . u n l o c k () ;

52 }

53 }

54

55 ...

(71)

Przykład praktyczny - fine-grained

Lista - fine-grained

(72)

FineList

1 p u b l i c b o o l e a n add ( T item ) { 2 int key = item . h a s h C o d e () ;

3 head . lock () ;

4 Node pred = head ;

5 try {

6 Node curr = pred . next ;

7 curr . lock () ;

8 try {

9 wh ile( curr . key < key ) {

10 pred . u n l o c k () ;

11 pred = curr ;

12 curr = curr . next ;

13 curr . lock () ;

14 }

15 if( curr . key == key ) {

16 r e t u r n fal se;

17 }

18 Node n e w N o d e = new Node ( item ) ;

19 n e w N o d e . next = curr ;

20 pred . next = n e w N o d e ;

21 r e t u r n true;

22 } f i n a l l y {

23 curr . u n l o c k () ;

24 }

25 } f i n a l l y {

26 pred . u n l o c k () ;

27 }

(73)

FineList

29 p u b l i c b o o l e a n r e m o v e ( T item ) {

30 Node pred = null, curr = null;

31 int key = item . h a s h C o d e () ;

32 head . lock () ;

33 try {

34 pred = head ;

35 curr = pred . next ;

36 curr . lock () ;

37 try {

38 wh ile( curr . key < key ) {

39 pred . u n l o c k () ;

40 pred = curr ;

41 curr = curr . next ;

42 curr . lock () ;

43 }

44 if( curr . key == key ) {

45 pred . next = curr . next ;

46 r e t u r n true;

47 }

48 r e t u r n fal se;

49 } f i n a l l y {

50 curr . u n l o c k () ;

51 }

52 } f i n a l l y {

53 pred . u n l o c k () ;

54 }

55 }

(74)

Przykład praktyczny - optimistic

Lista - optymistyczna

(75)

OptimisticList

1 p r i v a t e b o o l e a n v a l i d a t e ( Node pred , Node curr ) {

2 Node node = head ;

3 wh ile( node . key <= pred . key ) {

4 if( node == pred )

5 r e t u r n pred . next == curr ;

6 node = node . next ;

7 }

8 r e t u r n fal se;

9 }

(76)

OptimisticList

10 p u b l i c b o o l e a n add ( T item ) { 11 int key = item . h a s h C o d e () ;

12 wh ile(true) {

13 Node pred = head ;

14 Node curr = pred . next ;

15 wh ile( curr . key < key ) {

16 pred = curr ; curr = curr . next ;

17 }

18 pred . lock () ; curr . lock () ;

19 try {

20 if( v a l i d a t e ( pred , curr ) ) {

21 if( curr . key == key ) {

22 r e t u r n fal se;

23 } else {

24 Node node = new Node ( item ) ;

25 node . next = curr ;

26 pred . next = node ;

27 r e t u r n true;

28 }

29 }

30 } f i n a l l y {

31 pred . u n l o c k () ; curr . u n l o c k () ;

32 }

33 }

(77)

OptimisticList

35 p u b l i c b o o l e a n r e m o v e ( T item ) { 36 int key = item . h a s h C o d e () ;

37 wh ile(true) {

38 Node pred = head ;

39 Node curr = pred . next ;

40 wh ile( curr . key < key ) {

41 pred = curr ; curr = curr . next ;

42 }

43 pred . lock () ; curr . lock () ;

44 try {

45 if( v a l i d a t e ( pred , curr ) ) {

46 if( curr . key == key ) {

47 pred . next = curr . next ;

48 r e t u r n true;

49 } else {

50 r e t u r n fal se;

51 }

52 }

53 } f i n a l l y {

54 pred . u n l o c k () ; curr . u n l o c k () ;

55 }

56 }

57 }

(78)

OptimisticList

58 p u b l i c b o o l e a n c o n t a i n s ( T item ) { 59 int key = item . h a s h C o d e () ;

60 wh ile(true) {

61 Node pred = head ;

62 Node curr = pred . next ;

63 wh ile( curr . key < key ) {

64 pred = curr ; curr = curr . next ;

65 }

66 pred . lock () ; curr . lock () ;

67 try {

68 if( v a l i d a t e ( pred , curr ) ) {

69 r e t u r n( curr . key == key ) ;

70 }

71 } f i n a l l y {

72 pred . u n l o c k () ; curr . u n l o c k () ;

73 }

74 }

(79)

Przykład praktyczny - leniwa lista

Lista - leniwa

(80)

LazyList

1 p r i v a t e b o o l e a n v a l i d a t e ( Node pred , Node curr ) {

2 r e t u r n ! pred . m a r k e d && ! curr . m a r k e d && pred . next == curr ;

3 }

(81)

LazyList

4 p u b l i c b o o l e a n add ( T item ) { 5 int key = item . h a s h C o d e () ;

6 wh ile(true) {

7 Node pred = head ;

8 Node curr = head . next ;

9 wh ile( curr . key < key ) {

10 pred = curr ; curr = curr . next ;

11 }

12 pred . lock () ;

13 try {

14 curr . lock () ;

15 try {

16 if( v a l i d a t e ( pred , curr ) ) {

17 if( curr . key == key ) {

18 r e t u r n fal se;

19 } else {

20 Node node = new Node ( item ) ;

21 node . next = curr ;

22 pred . next = node ;

23 r e t u r n true;

24 }

25 }

26 } f i n a l l y {

27 curr . u n l o c k () ;

28 }

29 } f i n a l l y {

30 pred . u n l o c k () ;

31 }

32 }

33 }

(82)

LazyList

34 p u b l i c b o o l e a n r e m o v e ( T item ) { 35 int key = item . h a s h C o d e () ;

36 wh ile(true) {

37 Node pred = head ;

38 Node curr = head . next ;

39 wh ile( curr . key < key ) {

40 pred = curr ; curr = curr . next ;

41 }

42 pred . lock () ;

43 try {

44 curr . lock () ;

45 try {

46 if( v a l i d a t e ( pred , curr ) ) {

47 if( curr . key != key ) {

48 r e t u r n fal se;

49 } else {

50 curr . m a r k e d = true;

51 pred . next = curr . next ;

52 r e t u r n true;

53 }

54 }

55 } f i n a l l y {

56 curr . u n l o c k () ;

57 }

58 } f i n a l l y {

59 pred . u n l o c k () ;

60 }

61 }

(83)

LazyList

63 p u b l i c b o o l e a n c o n t a i n s ( T item ) { 64 int key = item . h a s h C o d e () ;

65 Node curr = head ;

66 wh ile( curr . key < key )

67 curr = curr . next ;

68 r e t u r n curr . key == key && ! curr . m a r k e d ;

69 }

(84)

Przykład praktyczny - kolejki

Przykład praktyczny - kolejki

(85)

Typy kolejek (i nie tylko)

Pojemność:

I

bounded

I

unbounded Metody:

I

total

I

partial

I

synchronous

(86)

Przykład praktyczny - BoundedQueue (partial)

Kolejka - BoundedQueue (partial)

(87)

BoundedQueue

1 p u b l i c cla ss B o u n d e d Q u e u e < T > { 2 p r i v a t e cl ass Node {

3 p u b l i c T val ue ;

4 p u b l i c v o l a t i l e Node next ; 5

6 p u b l i c Node ( T val ue ) {

7 this. v alu e = v alu e ;

8 }

9 }

10

11 R e e n t r a n t L o c k e n q L o c k = new R e e n t r a n t L o c k () ; 12 C o n d i t i o n n o t F u l l C o n d i t i o n = e n q L o c k . n e w C o n d i t i o n () ; 13 R e e n t r a n t L o c k d e q L o c k = new R e e n t r a n t L o c k () ; 14 C o n d i t i o n n o t E m p t y C o n d i t i o n = d e q L o c k . n e w C o n d i t i o n () ; 15

16 v o l a t i l e Node head = new Node (null) ; 17 v o l a t i l e tail = head ;

18

19 A t o m i c I n t e g e r size = new A t o m i c I n t e g e r (0) ; 20 int c a p a c i t y ;

21

22 p u b l i c B o u n d e d Q u e u e (int c a p a c i t y ) { 23 this. c a p a c i t y = c a p a c i t y ;

24 }

(88)

BoundedQueue

25 p u b l i c void enq ( T x ) {

26 b o o l e a n m u s t W a k e D e q u e u e r s = fa lse; 27 e n q L o c k . lock () ;

28 try {

29 wh ile( size . get () == c a p a c i t y ) 30 n o t F u l l C o n d i t i o n . a wai t () ;

31 Node e = new Node ( x ) ;

32 tail . next = e ;

33 tail = e ;

34 if( size . g e t A n d I n c r e m e n t () == 0) 35 m u s t W a k e D e q u e u e r s = true;

36 } f i n a l l y {

37 e n q L o c k . u n l o c k () ;

38 }

39 if( m u s t W a k e D e q u e u e r s ) {

40 d e q L o c k . lock () ;

41 try {

42 n o t E m p t y C o n d i t i o n . s i g n a l A l l () ;

43 } f i n a l l y {

44 d e q L o c k . u n l o c k () ;

45 }

46 }

Cytaty

Powiązane dokumenty

Z prezentowanych badań wynika, że o ile dla chłopców ważna jest sprawność ich nauczyciela wychowania fizycznego, jego kreatywność w doborze ćwiczeń oraz

Celem współpracy jest zapewnienie należytego bezpiecze- ństwa zdrowotnego Polakom w zakresie usług ratownictwa medycznego oraz warunków zatrudnienia

Materiały potrzebne do zabawy: „artykuły” do sklepików przygotowane przez dzieci, monety dla każdego ucznia – karta pracy nr 40 (dla każdego dziecka przeznaczamy na zakupy 6

Mówiąc krótko – celem standardów me- dycznych, takich jak DICOM i HL7, jest ułatwienie i przyśpieszenie integracji pomiędzy systemami, przez co koszty integracji są mniejsze,

Rezonans magnetyczny jest klinicznie sprawdzoną, powtarzalną, wiarygodną, nieinwazyjną metodą diagnostyczną stosowaną w ocenie morfologii, czynności (motoryki i hemodynamiki)

Dzięki stosunkowo krótkiemu czasowi wykonywania badanie opóźnionego wzmocnienia i badanie perfuzji pierwszego przejścia są, wraz z sekwencjami do oceny morfologii oraz

O  zezwierzęceniu w  kon- tekście przejawiania skłonności do  zadawania cierpień bliźniemu pisze Smaga w cytowanym już tutaj tekście, zwracając uwagę, że choć

Jeśli układ odniesienia porusza się względem powietrza, ruch ten wpływać musi na prędkość rozchodzenia się dźwięku w tym układzie.. A zatem, mierząc prędkość dźwięku