As known that List is not thread-safe, I add synchronized to the code in 2 methods shown below.
1.
public class TestSyn
{
public static void main( String[] args ) throws InterruptedException
{
List<String> list = new ArrayList<>();
for( int i = 0; i < 100000; i++ )
{
new Thread(
()->
{
synchronized( list )
{
list.add( Thread.currentThread().getName() );
}
} ).start();
}
Thread.sleep( 2000 );
System.out.println( list.size() );
}
}
public class TestSyn2
{
public static void main( String[] args ) throws InterruptedException
{
List<String> list = new ArrayList<>();
synchronized( list )
{
for( int i = 0; i < 10000; i++ )
{
new Thread( () -> list.add( Thread.currentThread().getName() ) )
.start();
}
}
Thread.sleep( 2000 );
System.out.println( list.size() );
}
}
The result of the first method was always 10000 which was correct,while the second one sometimes is less than 10000.
So, why does the second one cannot output the right result?
Just expanding on the answer that already was provided in comments (above).
The difference between your two versions is in which thread or threads lock the list
object's intrinsic mutex.
In the first version, the synchronized(list)
statement is executed by each one of the 100,000 new threads that your program creates. It is lexically contained within the lambda expression that generates the Runnable
delegates for each of the new threads.
In the second version, the synchronized(list)
statement is only ever executed one time, by the program's main
thread. It appears outside of the lambda. The 100,000 new threads mutate the shared list without any synchronization, and the fact that main()
executes inside the synchronized
block means nothing because no other thread ever tries to synchronize on the same object.
Also note: Although the first version of your program is "safe," it also is kind of pointless. None of your 100,000 new threads ever does anything at all outside of the synchronized
block. That means, none of your 100,000 new threads ever does anything concurrently with any of the others. But concurrency is the only reason for creating threads.