Thursday, April 18, 2024
HomeJavaJava Concurrency: The Lock interface - Java Code Geeks

Java Concurrency: The Lock interface – Java Code Geeks


Beforehand we applied a thread protected counter utilizing synchronized. We want to swift from synchronized blocks to one thing extra versatile with extra options, that is had been locks are of use. On this weblog we are going to concentrate on Java’s Lock interface.

The Lock interface helps three types of lock acquisition interruptible, non-interruptible, and timed.

We are able to purchase locks between threads. A thread will wait till the lock is launched from the thread holding the lock:

@Take a look at
    void lock() throws InterruptedException {
        Thread withDelayedLock = new Thread(() -> {
            lock.lock();
            log.data("Acquired delayed");
            lock.unlock();
        });

        lock.lock();
        withDelayedLock.begin();

        Thread.sleep(500);
        log.data("Will launch");
        lock.unlock();
        withDelayedLock.be a part of();
    }

For the reason that threads blocks on the lock we would as properly interrupt the thread. On this case we will lock lockInterruptibly, and apply any logic in case of an Interrupt:

@Take a look at
    void lockInterruptibly() throws InterruptedException {
        Thread withDelayedLock = new Thread(() -> {
            strive {
                lock.lockInterruptibly();
            } catch (InterruptedException e) {
                log.error("interrupted whereas ready",e);
            }
        });

        lock.lock();
        withDelayedLock.begin();
        withDelayedLock.interrupt();
        lock.unlock();
        withDelayedLock.be a part of();
    }

A thread may also attempt to purchase a lock which is already acquired, and exit instantly as a substitute of blocking.

@Take a look at
    void tryLock() throws InterruptedException {
        Thread withDelayedLock = new Thread(() -> {
            boolean locked = lock.tryLock();
            assertFalse(locked);
        });

        lock.lock();
        withDelayedLock.begin();
        Thread.sleep(500);
        lock.unlock();
        withDelayedLock.be a part of();
    }

Additionally a time interval may be specified till the lock is acquired.

@Take a look at
    void tryLockTime() throws InterruptedException {
        Thread withDelayedLock = new Thread(() -> {
            strive {
                boolean locked = lock.tryLock(100, TimeUnit.MILLISECONDS);
                assertFalse(locked);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        lock.lock();
        withDelayedLock.begin();
        Thread.sleep(500);
        lock.unlock();
        withDelayedLock.be a part of();
    }

One other factor of significance with locks is reminiscence.

From the documentation

All {@code Lock} implementations <em>should</em> implement the identical
* reminiscence synchronization semantics as offered by the built-in monitor
* lock, as described in
* Chapter 17 of
* <cite>The Java Language Specification</cite>:
*
<ul>*
 	<li>A profitable {@code lock} operation has the identical reminiscence
* synchronization results as a profitable <em>Lock</em> motion.
*</li>
 	<li>A profitable {@code unlock} operation has the identical
* reminiscence synchronization results as a profitable <em>Unlock</em> motion.
*</li>
</ul>

To ensure that the outcomes to be flushed on the primary reminiscence we have to use lock and unlock.
Take the next instance

personal Lock lock = new ReentrantLock();
    personal String threadAcquired = "principal";

    @Take a look at
    void wrongMemoryVisibility() throws InterruptedException {
        Thread withDelayedLock = new Thread(() -> {
            lock.lock();
            strive {
                threadAcquired = "delayed";
                System.out.println("Acquired on delayed");
                Thread.sleep(500);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } lastly {
                lock.unlock();
            }

        });

        lock.lock();
        strive {
            withDelayedLock.begin();
            Thread.sleep(500);
        } lastly {
            lock.unlock();
        }

        whereas (true) {
            System.out.println("Presently acquired " + threadAcquired);
            if (threadAcquired.equals("delayed")) {
                break;
            }
        }

        withDelayedLock.be a part of();
        threadAcquired = "principal";
    }

We print the variable threadAcquired by the primary thread whereas it’s modified by the thread with a Delayed lock.
After just a few runs a state of affairs the place the threadAcquired variable has a stale worth on the primary thread will seem.

Acquired on delayed
Presently acquired principal

We did this on function, on an actual world drawback we should always not entry variables like threadAcquired with out correct synchronisation, for instance we should always have acquired the lock first, this manner the reminiscence could be synchronised and we’d have an updated worth.

@Take a look at
    void correctMemoryVisibility() throws InterruptedException {
        Thread withDelayedLock = new Thread(() -> {
            lock.lock();
            strive {
                threadAcquired = "delayed";
                System.out.println("Acquired on delayed");
                Thread.sleep(500);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } lastly {
                lock.unlock();
            }

        });

        lock.lock();
        strive {
            withDelayedLock.begin();
            Thread.sleep(500);
        } lastly {
            lock.unlock();
        }

        whereas (true) {
            lock.lock();
            strive {
                System.out.println("Presently acquired " + threadAcquired);
                if (threadAcquired.equals("delayed")) {
                    break;
                }
            } lastly {
                lock.unlock();
            }
        }

        withDelayedLock.be a part of();
    }

That’s all for now, we are going to later proceed on totally different kind of locks and the Situation interface.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments