1

Here is my main class that initializes and starts 5 different Threads:

public class Server implements Runnable { Server1 server1; Thread server1Thread; public Server() {} @Override public void run() { server1 = new Server1(); server1Thread = new Thread(server1); server1Thread.start(); } public static void main(String[] args) { for (int i = 0; i < 5; i++) { Server s = new Server(); s.run(); } } } 

Here is my Server1 Runnable:

import java.util.concurrent.ConcurrentHashMap; public class Server1 implements Runnable { private ConcurrentHashMap<Integer, Integer> storage= new ConcurrentHashMap<>(); public Server1() {} @Override public void run() { synchronized (this){ for (int i = 0; i < 10; i++) { storage.put(i, (int)(Math.random()*100)); } for (int i : storage.keySet()) { System.out.print("(" + i + "," + storage.get(i) + ") "); } System.out.println(); } } } 

It puts in ConcurrentHashMap storage keys from 0 to 9 and assigns them a random value between 0 and 100. After that it prints it and prints new line at the end. I have user synchronized block to make sure the thread itself access keys correctly but it prints something like this:

(0,8) (0,87) (1,60) (1,14) (2,20) (2,70) (3,5) (0,74) (0,42) (1,22) (4,96) (0,85) (1,97) (2,75) (3,68) (4,3) (5,49) (6,3) (7,9) (8,47) (9,52) (3,2) (5,74) (2,86) (1,48) (3,5) (6,0) (4,0) (7,86) (4,22) (8,20) (2,17) (9,87) (5,96) (5,15) (6,15) (6,92) (7,48) (8,93) (9,67) (3,87) (7,43) (4,34) (5,48) (8,91) (9,64) (6,84) (7,75) (8,47) (9,87) 

which obviously means that some thread prints more that 10 keys that I assigned to it. How do I make every thread print exactly 10 keys and values that it is assigned to them and ensure concurrency here?

I am not sure how to test it.

3
  • there are 50 pairs, the keys are within range, random values are whatever. so each one looks good, doesn't it? they write to stdout simultaneously, though. Commented Dec 11, 2019 at 21:03
  • I suggest trying synchronized(System.out) instead of using synchronized(this). If you do that, your threads will at least share the same lock. Commented Dec 11, 2019 at 21:06
  • The threads are generating only 10 entries. You should synchronize on something that's shared across the threads. either a static key or the class itself. That is the issue here. Commented Dec 11, 2019 at 21:06

2 Answers 2

1

Your threads don't share any internal state. They're working fine, but the output is interleaved.

For instance if you used a StringBuilder to do the I/O in one operation, you should see correct output.

 StringBuilder buff = new StringBuilder(); for (int i : storage.keySet()) { buff.append("(" + i + "," + storage.get(i) + ") "); } System.out.println(buff); 

There is no good reason for Server to be Runnable, or even to create any instances of it.

You do not share any of the maps. If you did, then you would also want to share a common lock, but this is not the usual way to use ConcurrentMap.

Sign up to request clarification or add additional context in comments.

2 Comments

This is a query for learning purposes. Since the run block of Server1 is synchronized, it means that only one thread can access the synchronized block at a single given point of time. That being the case how is it possible for the output to be interleaved?
@Vinnie One thread for each Object locked. Each thread has a different object.
0

All you had to do was synchronized (Server1.class) as that is common across threads. Not the instance

Here is the verified output:

(0,75) (1,9) (2,61) (3,73) (4,55) (5,34) (6,34) (7,74) (8,41) (9,0)

(0,30) (1,42) (2,46) (3,66) (4,12) (5,17) (6,62) (7,59) (8,74) (9,4)

(0,50) (1,16) (2,29) (3,74) (4,68) (5,42) (6,33) (7,91) (8,25) (9,7)

(0,49) (1,10) (2,39) (3,94) (4,12) (5,55) (6,54) (7,89) (8,21) (9,75)

(0,77) (1,10) (2,37) (3,32) (4,73) (5,39) (6,64) (7,98) (8,96) (9,44)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.