Java lock conditions seem to not be working right - java

I have a problem where there is a BoundedBuffer and there are Consumers and Producers, the producers fill the buffer and consumers remove from the buffer.
I'm using threads for the Consumers and Producers, and i was trying to use lock conditions to ensure that the buffer isn't full to the producer and isn't empty for the consumer.
Unfortunately it's not working the way I wanted, it seems that the Consumer/Producer, when they are in Condition.await, don't let the other threads work. Shouldn't they let them?
Here is my code
class main
{
public static void main (String[] args) throws InterruptedException
{
final int N = Integer.parseInt(args[0]);
BoundedBuffer teste = new BoundedBuffer(N);
Thread c = new Consumidor(teste,N);
Thread p = new Produtor(teste,N);
c.start();
p.start();
c.join();
p.join();
}
}
class BoundedBuffer
{
ArrayList<Integer> array;
int index;
int size;
Lock l = new ReentrantLock();
Condition notFull = l.newCondition();
Condition notEmpty = l.newCondition();
BoundedBuffer(int N)
{
this.array=new ArrayList<Integer>(N);
this.index = 0;
this.size=N;
}
public synchronized void put(int e) throws InterruptedException
{
l.lock();
try
{
while(this.index >= this.size)
{
notFull.await();
}
this.array.add(index,e);
this.index++;
notEmpty.signal();
}
finally
{
l.unlock();
}
}
public synchronized int get() throws InterruptedException
{
int i;
l.lock();
try
{
while(this.index <=0)
{
notEmpty.await();
}
this.index--;
notFull.signal();
i = this.array.get(index);
}
finally
{
l.unlock();
}
return i;
}
}
class Consumidor extends Thread
{
private BoundedBuffer b;
final int j;
public Consumidor(BoundedBuffer b, int j)
{
this.b = b;
this.j=j;
}
public void run()
{
int a;
for (int i = 0; i < j ;++i)
{
try
{
a=b.get();
System.out.println("GET: " +a);
}
catch (Exception e) {}
}
}
}
class Produtor extends Thread
{
private BoundedBuffer b;
final int j;
public Produtor(BoundedBuffer b, int j)
{
this.b = b;
this.j=j;
}
public void run()
{
int a;
for (int i = 0; i < j; ++i)
{
try
{
b.put(i);
System.out.println("PUT: " +i);
}
catch (Exception e) {}
}
}
}
Thanks in advance

Don’t mix intrinsic locks (meaning synchronized) with reentrantLocks. This code is trying to acquire the intrinsic lock and then the reentrantlock.
Putting synchronized on an instance method requires the thread calling the method to acquire the intrinsic lock on the instance. ReentrantLock is a separate locking construct that does not use that keyword. Mixing the two mechanisms is unnecessary and can only cause trouble.
(Specifically the code is calling await on the condition object, which causes the thread to release the reentrant lock, but the thread keeps holding onto the intrinsic lock, preventing the other thread from entering a synchronized method.)
The fix for this is to delete the synchronized keyword from your code.

Related

Thread safe read/write to a counter

Im trying to make 2 threads that read/write to a counter using thread safe methods.
I have written some code to try test this but the read thread just reads the counter at its max (1000)
Main:
public static void main(String[] args) {
Counter c = new Counter();
Thread inc = new Increment(c);
Thread read = new Read(c);
inc.start();
read.start();
}
Counter:
public class Counter {
private int count;
public Counter() {
count = 0;
}
public synchronized void increment() {
count++;
}
public synchronized int getVal() {
return count;
}
}
Increment:
public class Increment extends Thread {
private static final int MAX = 1000;
private Counter myCounter;
public Increment(Counter c) {
myCounter = c;
}
public void run() {
for (int i = 0; i < MAX; i++) {
myCounter.increment();
}
}
}
Read:
public class Read extends Thread {
private static final int MAX = 1000;
private Counter myCounter;
public Read(Counter c) {
myCounter = c;
}
public void run() {
for (int i = 0; i < MAX; i++) {
System.out.println(myCounter.getVal());
}
}
}
Would I be better off using Atomic Integer to hold the value of the counter to allow me to safely increment it and get the value?
Your code is perfectly fine as is. It just so happened that your increment thread finished all its increments before the read thread got a chance to read. 1,000 increments takes almost no time at all.
If you want interleave execution of Read thread and Increment thread much more often then the natural operating system thread pre-emption, just make each thread give up their lock (by calling <lockedObject>.wait() followed by <lockedObject>.notify() or notifyAll() in the respective run() methods:
[In Reader]:
public void run() {
for (int i = 0; i < MAX; i++) {
synchronized (myCounter) {
System.out.println(myCounter.getVal());
try {
myCounter.wait(0L, 1);
myCounter.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
[In Increment]:
public void run() {
for (int i = 0; i < MAX; i++) {
synchronized (myCounter) {
myCounter.increment();
try {
myCounter.wait(0L, 1);
myCounter.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Upping the MAX constant to 1_000_000_000 (1 billion) made the treads interleave as well every now and then (on my machine interleave happened just by gazing at few printouts between 150 and 400_000 iterations).

Puzzle about two workers and a cart. Usage lock and conditions doesn't work

When using synchronized block or method, we synchronized by mutable object. But I don't understand how to use Locks with Conditions from j.u.c.. I'm trying to solve puzzle with two workers and a cart with lock and conditions. When first worker add weight to the cart - second wait. When cart is full, than first worker wait and second releases the cart.
I create two threads for each worker and use one cart. But in reality only one thread performs (worker, that add weight) until cart is full. Than program blocks. What I'm doing wrong and what I misunderstand?
That's my implementation of this puzzle.
package puzzles.workers;
public enum WorkerType {
ADDER, REDUCER;
}
Cart class
package puzzles.workers;
public class Cart {
private static final int INITIAL_CAPACITY = 10;
private static final int INITIAL_WEIGHT = 0;
private int capacity;
private int weight;
public Cart() {
this(INITIAL_CAPACITY);
}
public Cart(int capacity) {
this.capacity = capacity;
weight = INITIAL_WEIGHT;
}
public void addWeight() {
weight++;
}
public void reduceWeight() {
weight--;
}
public int getCapacity() {
return capacity;
}
public int getWeight() {
return weight;
}
}
Worker class.
package puzzles.workers;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class WorkerWithLock implements Runnable {
private final Cart cart;
private WorkerType workerType;
final Lock lock = new ReentrantLock();
final Condition whenEmpty = lock.newCondition();
final Condition whenFull = lock.newCondition();
public WorkerWithLock(Cart cart, WorkerType workerType) {
this.cart = cart;
this.workerType = workerType;
}
#Override
public void run() {
while (true) {
if (workerType == WorkerType.ADDER) {
try {
addWeight();
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
} else {
try {
reduceWeight();
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
}
public void addWeight() throws InterruptedException {
lock.lock();
try {
while (cart.getWeight() == (cart.getCapacity() - 1)) {
whenFull.await();
}
cart.addWeight();
System.out.println("++ weight is: " + cart.getWeight());
whenEmpty.signalAll();
Thread.sleep(500);
} finally {
lock.unlock();
}
}
public void reduceWeight() throws InterruptedException {
lock.lock();
try {
while (cart.getWeight() == 0) {
whenEmpty.await();
}
cart.reduceWeight();
System.out.println("-- weight is: " + cart.getWeight());
whenFull.signalAll();
Thread.sleep(500);
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Cart cart = new Cart(5);
WorkerWithLock adder = new WorkerWithLock(cart, WorkerType.ADDER);
WorkerWithLock reducer = new WorkerWithLock(cart, WorkerType.REDUCER);
new Thread(reducer).start();
new Thread(adder).start();
}
}
It is a kind of a race condition
That is because both threads are waiting.
One in addWeightand one in reduceWeight.
First the reducer stops, if weight is 0. At this time, the adder is may be not already started.
Than the adder stops, if weight = cpacity - 1
Now, both are waiting for an interrupt().
EDIT1. See my comments in the code
public void addWeight() throws InterruptedException {
lock.lock();
try {
while (cart.getWeight() == (cart.getCapacity() - 1)) {
whenFull.await(); //<-- ADDER waits here
}
cart.addWeight();
System.out.println("++ weight is: " + cart.getWeight());
whenEmpty.signalAll(); //<-- Never called since both are waiting
Thread.sleep(500);
} finally {
lock.unlock();
}
}
public void reduceWeight() throws InterruptedException {
lock.lock();
try {
while (cart.getWeight() == 0) {
whenEmpty.await(); //<-- REDUCER waits here
}
cart.reduceWeight();
System.out.println("-- weight is: " + cart.getWeight());
whenFull.signalAll(); //<-- Never called since both are waiting
Thread.sleep(500);
} finally {
lock.unlock();
}
}
EDIT2: Ok, now I understand the behaviour.
Your code is designed to synchronize ONE object for multiple threads, but your are using TWO objects.
Every of your both WorkerWithLock Objects has its own Lock and Condition objects. So calls of lock.lock() and whenFull.signalAll() in object ADDER does not effect Object REDUCER.
Your code will work if you make the lock and condition variables static, so that both objects are working with the same lock and the same condition
final static Lock lock = new ReentrantLock();
final static Condition whenEmpty = lock.newCondition();
final static Condition whenFull = lock.newCondition();
Sometimes multithreading is hard :)

multithreading java xync

I'm new to multithreading. I need to calculate integral by partial sums using multiple threads. I want to find out if all threads finished calculating to show general sum, I'm doing it using sleep(500) but it's stupid. How can i do it by the right way?
public class MainClass {
private static int threadCount=10;
public static double generalSum=0;
private static ArrayList<CalculatingThread> threads;
public static void main(String[] args){
Calculator.setA(0);
Calculator.setB(2);
Calculator.setN(500);
threads=new ArrayList<CalculatingThread>();
int div=500/threadCount;
for (int i=0; i<div;i++){
CalculatingThread thread=new CalculatingThread();
thread.setJK(i*10,(i+1)*10-1);
thread.start();
threads.add(thread);
}
try {
Thread.currentThread().sleep(500);
System.out.println(generalSum);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class CalculatingThread extends Thread {
private int j;
private int k;
#Override
public void run(){
System.out.println("Partial sum: " + Calculator.calcIntegral(j, k));
Calculator.addToSumm(Calculator.calcIntegral(j, k));
//this.notify();
}
public void setJK(int j,int k) {
this.j = j;
this.k=k;
}
}
public class Calculator {
private static double a;
private static double b;
private static int n;
private static double InFunction(double x){
return Math.sin(x);
}
private double sum=0;
public static void setA(double a) {
Calculator.a = a;
}
public static void setB(double b) {
Calculator.b = b;
}
public static void setN(int n) {
Calculator.n = n;
}
public static double calcIntegral(int j,int k)
{
double result, h;
int i;
h = (b-a)/n; //Шаг сетки
result = 0;
for(i=j; i <= k; i++)
{
result += InFunction(a + h * i - h/2); //Вычисляем в средней точке и добавляем в сумму
}
result *= h;
return result;
}
public static synchronized void addToSumm(double sum){
MainClass.generalSum+=sum;
}
}
P.S. sorry, i know code is stupid, i will refactor it later
Replace
Thread.currentThread().sleep(500);
with
for (Thread thread : threads) {
thread.join();
}
This will make main thread to wait until all the created threads get completed. Also you can refer wait until all threads finish their work in java
you can use join to make the main thread wait for the others:
The join method allows one thread to wait for the completion of
another. If t is a Thread object whose thread is currently executing,
t.join(); causes the current thread to pause execution until t's
thread terminates. Overloads of join allow the programmer to specify a
waiting period. However, as with sleep, join is dependent on the OS
for timing, so you should not assume that join will wait exactly as
long as you specify.
save every thread you create in an array and then do join on them
so your main should look like
public class MainClass {
private static int threadCount=10;
public static double generalSum=0;
private static ArrayList<CalculatingThread> threads;
public static void main(String[] args){
Calculator.setA(0);
Calculator.setB(2);
Calculator.setN(500);
threads=new ArrayList<CalculatingThread>();
int div=500/threadCount;
for (int i=0; i<div;i++){
CalculatingThread thread=new CalculatingThread();
thread.setJK(i*10,(i+1)*10-1);
thread.start();
threads.add(thread);
}
try {
for (Thread curr: threads) {
curr.join();
}
System.out.println(generalSum);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
now on a side note, no series program is using sleep when it wants to wait. sleep is only used when you actually need a delay in a background thread
P.S.
do not refactor the code. it is excellent to post it like that, so i can see every mistake you do if u do. a lot better then most people posting only 1 line and then there is nothing i can do but ask for more details

Java unisex bathroom

I have to solve this problem using Java semaphores, but I have no idea how, and I cannot find any related Java materials. This is how it goes:
There are to kinds of threads: men and women. Both wants to use same resources which quantity is BATHROOM_SIZE. 5 rules:
Every thread, after signaling need of using resource, should wait until he will be able to use it.
Prevent situation, when more than BATHOOM_SIZE threads is using resource concurrently.
Prevent woman and man use bathoom in the same time.
Threads should use resources concurrently. If there are many threads of one type, up to BATHROOM_SIZE threads should use resource.
Prevent starvation.
Results
Works for:
1woman, 1man, 5women, 5men
Fails for:
5women1men, 5men1women, 2men2women, 5men5women.
I've been trying to make it work since Monday and now I've run out of ideas.
Code
So my task is to write Bathroom.java class which implements BathroomInterface:
public interface BathroomInterface {
public static final int BATHROOM_SIZE = 3; //3 is just example
void manEnter();
void manExit();
void womanEnter();
void womanExit();
}
In system there are a number of man and woman threads which work like this:
for(int i = 0; i < n; i++) {
bathroom.manEnter();
//uses bathroom random amount of time
bathroom.manExit();
}
for(int i = 0; i < m; i++) {
bathroom.womanEnter();
//uses bathroom random amount of time
bathroom.womanExit();
}
I also have scheme of Bathroom.java class, I have to extend:
import java.util.concurrent.Semaphore;
public class Bathroom implements BathroomInterface {
private Semaphore mutex = new Semaphore(1, true);
public void womanEnter() {
mutex.acquireUninterruptibly();
}
public void womanExit() {
mutex.release();
}
public void manEnter() {
mutex.acquireUninterruptibly();
}
public void manExit() {
mutex.release();
}
}
This is what I made so far:
import java.util.concurrent.Semaphore;
public class Bathroom implements BathroomInterface {
int manW=0, manU=0, womanW=0, womanU=0; //*U-using, *W-waiting
private Semaphore mutex = new Semaphore(1, false);
public void womanEnter() {
womanW++;
StateChange();
}
public void womanExit() {
womanU--;
mutex.release();
StateChange();
}
public void manEnter(){
manW++;
StateChange();
}
public void manExit() {
manU--;
mutex.release();
StateChange();
}
void StateChange() {
if(womanU==0 && manU==0) {
if(manW>womanW) {
while(manW>0 && manU<BATHROOM_SIZE) {
manW--;
manU++;
mutex.acquireUninterruptibly();
}
}
else {
while(womanW>0 && womanU<BATHROOM_SIZE) {
womanW--;
womanU++;
mutex.acquireUninterruptibly();
}
}
}
if(womanU==0 && manU<BATHROOM_SIZE) {
while(manW>0 && manU<BATHROOM_SIZE) {
manW--;
manU++;
mutex.acquireUninterruptibly();
}
}
if(manU==0 && womanU<BATHROOM_SIZE) {
while(womanW>0 && womanU<BATHROOM_SIZE) {
womanW--;
womanU++;
mutex.acquireUninterruptibly();
}
}
}
}
Actually this exercise is done using a monitor, and not a semaphore. What you're doing is mostly fine, you're missing the conditions. So, in your bathroom class, declare:
a lock:
private Lock lock = new ReentrantLock();
2 conditions or queues, attached to your lock:
private Condition womenWaitingQueue = lock.newCondition();
private Condition menWaitingQueue = lock.newCondition();
2 counters to know how many are waiting, and 2 to know how many are using:
private int womenWaitingN = 0;
private int menWaitingN = 0;
private int womenUsingN = 0;
private int menUsingN = 0;
and of course, the number of resources:
private final int BATHROOM_CAPACITY = 5;
private int free_resources = BATHROOM_CAPACITY;
all 4 functions were here, but removed because of the homework tag
The important thing here is to prevent starvation, by not allowing any men to enter the bathroom if there are women waiting and viceversa.
so, conditions are that if a man wants to enter to the bathroom, it has to check if the bathroom has at least 1 free spot (using free resources) and if there are women in the bathroom (using womenUsingN). If any of these 2 conditions are not met, the man must wait(using the menWaitingQueue):
menWaitingQueue.await();
when a man leaves the bathroom, it has to check if there are any women waiting (womenWaitingN), if there are, they get notified:
womanWaitingQueue.signal();
because of the menUsingN counter, women signaled by this wont be able to enter until there are no men in the bathroom. If there are no women waiting, then a man can be signaled to enter the bathroom. This prevents starvation because priority is given to the opposite sex (if waiting).
The last thing, is that every function must lock/unlock the lock at beginning/end of each enter/exit function.
lock.lock();
lock.unlock();
I think with this new information you'll be able to make the functions on your own. Good luck!
I think you struggle with the whole mutex.acquire and mutex.release semantics, especially with what the mutex is actually supposed to guard. Let me try to simplify the problem a little to give you a hint as to how to approach this.
You are asked to implement a concurrency object that's more complicated than a simple semaphore, with two client classes and starvation prevention. I'm not going to do that for you, but i'm going to show you how a simple semaphore looked like in the pre-Java6 days:
public class Resource {
private int numClients = 0;
private final int maxClients;
public Resource(int maxClients) {
this.maxClients = maxClients;
}
public synchronized void acquire() {
while (!clientCanAcquire()) {
try {
wait();
} catch (InterruptedException e) {
}
}
++numClients;
printState();
}
public synchronized void release() {
--numClients;
printState();
notify();
}
private boolean clientCanAcquire() {
return numClients < maxClients;
}
private void printState() {
System.out.println("Resource is currently acquired by " + numClients
+ " clients");
}
}
A Client can access this as follows:
import java.util.Random;
public class Client implements Runnable {
private Resource resource;
private Random rnd = new Random();
public Client(Resource resource) {
this.resource = resource;
}
public void run() {
try {
Thread.sleep(rnd.nextInt(1000));
resource.acquire();
Thread.sleep(rnd.nextInt(1000));
resource.release();
} catch (InterruptedException e) {
}
}
}
and the simplest application that can drive the whole thing would look like this:
public class App {
public static void main(String[] arg) {
Resource r = new Resource(3);
for (int i = 0; i < 10; i++) {
Thread client = new Thread(new Client(r));
client.start();
}
}
}
Resource stores the information it needs to determine when a client can access in internal variables. In a multithreaded application, access to these variables must be synchronized. Shown here is the simplest way to do this, but you could also say
private Object mutex = new Object();
and then
synchronized (mutex) { }
or any other type of mutex.
Your problem is more complicated than a simple ordinary semaphore, but the underlying logic should be pretty similar.
#Th0rndike ok, i followed your hints and wrote sth like this:
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.*;
public class Bathroom implements BathroomInterface {
private Semaphore mutex = new Semaphore(1, false);
private Lock lock = new ReentrantLock();
private Condition womenWaitingQueue = lock.newCondition();
private Condition menWaitingQueue = lock.newCondition();
private int womenWaitingN = 0;
private int menWaitingN = 0;
private int womenUsingN = 0;
private int menUsingN = 0;
private int free_res = BATHROOM_SIZE;
public void womanEnter() {
lock.lock();
if(free_res>0 && menUsingN==0) {
womenUsingN++;
free_res--;
mutex.acquireUninterruptibly();
}
else
try {
womenWaitingQueue.await();
}
catch(Exception e) {
System.out.println("E!");
}
lock.unlock();
}
public void womanExit() {
lock.lock();
womenUsingN--;
free_res++;
mutex.release();
if(menWaitingN>0) {
try {
menWaitingQueue.signal();
}
catch(Exception e) {
System.out.println("E!");
}
}
lock.unlock();
}
public void manEnter() {
lock.lock();
menUsingN++;
free_res--;
if(free_res>0 && womenUsingN==0) {
mutex.acquireUninterruptibly();
}
else
try {
menWaitingQueue.await();
}
catch(Exception e) {
System.out.println("E!");
}
lock.unlock();
}
public void manExit() {
lock.lock();
menUsingN--;
free_res++;
mutex.release();
if(womenWaitingN>0) {
try {
womenWaitingQueue.signal();
}
catch(Exception e) {
System.out.println("E!");
}
}
lock.unlock();
}
}
But when I submit it to the automated program checker, in 1man and 1woman tests everything is ok, but in the rest, it returns "realtime exceeded" error. If I remove lock.lock()/unlock(), "realtime exceeded" errors will change to "wrong answer".
There is a solution at http://se.inf.ethz.ch/courses/2013a_spring/ccc/
You may refer that for some help.

locking each item in array by java

suppose we have these classes:
public class Record {
int key;
int value;
Record(){
this.key=0;
this.value=0;
}
Record(int key,int value){
this.key=key;
this.value=value;
}
public class Table {
static final Record[] table = new Record [100];
static final Object[] locks = new Object[table.length];
static{
for(int i = 0; i < table.length; i++) {
locks[i] = new Object();
}
table[0]=new Record(0,0);
table[1]=new Record(1,10);
table[2]=new Record(2,20);
table[3]=new Record(3,30);
}
}
And i want to implement in TRansaction class these method
void setValueByID(int key, int value)
The key-value pair (record) is locked(it cannot be read/written from other transactions) until the setValueByID method finishes.
int getValueByID(int key)
The key-value pair (record) is locked until the transaction commits
void commit()
it unlocks all the key-value pairs (records) locked in the current transaction
So, my implementation is :
class Transaction extends Thread {
//there is no problem here
public void setValueByID(int key, int value){
synchronized(Table.locks[key]) {
Table.table[key].key=key;
}
}
//the problem is here...
//how can i make other thread wait until current thread calls Commit()
public int getValueByID(int key){
int value=0;
synchronized(Table.locks[key]){
value= Table.table[key].key;
}
return value;
}
void commit(){
}
Ahmad
You cannot use synchronized blocks to achieve it, instead you will need to use something like locks.
public Main {
public static void main(String[] args) {
final Transaction T = new Transaction();
for (int n = 0; n < 10; n++) {
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
T.setValueByID(i % 100, i);
T.getValueByID(i % 100);
if (i % 20 == 0) T.commit();
}
}
}).start();
}
}
}
class Table {
static final Record[] table = new Record[100];
static final ReentrantLock[] locks = new ReentrantLock[table.length];
static {
for (int i = 0; i < table.length; i++) {
locks[i] = new ReentrantLock();
}
table[0] = new Record(0, 0);
table[1] = new Record(1, 10);
table[2] = new Record(2, 20);
table[3] = new Record(3, 30);
}
}
class Transaction {
private ThreadLocal<Set<ReentrantLock>> locks = new ThreadLocal<Set<ReentrantLock>>() {
#Override
protected Set<ReentrantLock> initialValue() {
return new HashSet<ReentrantLock>();
}
};
private void attainLock(int key) {
final ReentrantLock lock = Table.locks[key];
lock.lock();
locks.get().add(lock);
}
private void releaseLock(int key) {
final ReentrantLock lock = Table.locks[key];
releaseLock(lock);
}
private void releaseLock(ReentrantLock lock) {
final Set<ReentrantLock> lockSet = locks.get();
if (!lockSet.contains(lock)) {
throw new IllegalStateException("");
}
lockSet.remove(lock);
lock.unlock();
}
private void releaseLocks() {
final Set<ReentrantLock> lockSet = new HashSet<ReentrantLock>(locks.get());
for (ReentrantLock reentrantLock : lockSet) {
releaseLock(reentrantLock);
}
}
public void setValueByID(int key, int value) {
attainLock(key);
Table.table[key].key = key;
releaseLock(key);
}
public int getValueByID(int key) {
attainLock(key);
return Table.table[key].key;
}
void commit() {
releaseLocks();
}
}
The problem with locks is that during your transaction, if you do not follow an order while attaining the locks, you can run into deadlocks! Also, you need to ensure you handle exceptions properly and always release the locks by calling commit().
This sort of synchronization is achieved using the wait()/notify() methods with some sort of lock. Read the Java tutorial on them (and other synchronization concepts) here.
Ideally you need to become familiar with the ReadWriteLock of java concurrent package. setValueId should obtain a write lock and hold it until transaction commits. getValueId only needs a read lock that can be shared by other read locks and be released when the method ends.
Also take into account some timeout so that the locks are not held indefinitely.
Research for:
read/write lock pattern
isolation levels in database systems
transaction handling

Categories

Resources