Ed *_*lle 3 java multithreading makefile
使用线程同步,Java似乎不是100%准确.此示例中的代码打印一个静态整数的值,该值由每个线程递增.如果输出包含相同的数字,uniq将多次识别它.每个示例都由Makefile脚本运行,以帮助说明问题.每个示例使用不同的同步/锁定方法,但似乎没有一个方法在100%的时间内都能正常工作.大多数复制发生在循环的早期,至少在这个系统上.
Makefile文件:
JAVA=/usr/local/jdk/bin/java
JAVAC=$(JAVA)c
build:
$(JAVAC) Synchron.java
$(JAVAC) SynchronVolatile.java
$(JAVAC) SynchronFinal.java
$(JAVAC) SynchronThis.java
$(JAVAC) SynchronA.java
$(JAVAC) SynchronObj.java
run:
$(JAVA) Synchron | sort | uniq -c | egrep -v '^\s+1\s+' ; /bin/true
$(JAVA) SynchronVolatile | sort | uniq -c | egrep -v '^\s+1\s+' ; /bin/true
$(JAVA) SynchronFinal | sort | uniq -c | egrep -v '^\s+1\s+' ; /bin/true
$(JAVA) SynchronThis | sort | uniq -c | egrep -v '^\s+1\s+' ; /bin/true
$(JAVA) SynchronA | sort | uniq -c | egrep -v '^\s+1\s+' ; /bin/true
$(JAVA) SynchronObj | sort | uniq -c | egrep -v '^\s+1\s+' ; /bin/true
Run Code Online (Sandbox Code Playgroud)
Synchron.java:
import java.io.*;
import java.util.*;
public class Synchron implements Runnable {
static int a;
synchronized public void adder() {
Synchron.a++;
System.out.println( Synchron.a );
}
public void run() {
while( Synchron.a < 65535 ) {
adder();
}
}
public static void main( String []args ) {
ArrayList <Thread>al = new ArrayList<Thread>();
try {
int i;
for( i = 0; i<10 ; i++ ) {
Synchron s = new Synchron();
Thread t = new Thread( s );
al.add(t);
t.start();
}
for( Thread t : al ) {
t.join();
}
}
catch( Exception e ) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
SynchronVolatile.java:
import java.io.*;
import java.util.*;
public class SynchronVolatile implements Runnable {
static int a;
static volatile Object o = new Object();
public void adder() {
synchronized( SynchronVolatile.o ) {
SynchronVolatile.a++;
}
System.out.println( SynchronVolatile.a );
}
public void run() {
while( SynchronVolatile.a < 65535 ) {
adder();
}
}
public static void main( String []args ) {
ArrayList <Thread>al = new ArrayList<Thread>();
try {
int i;
for( i = 0; i<10 ; i++ ) {
SynchronVolatile s = new SynchronVolatile();
Thread t = new Thread( s );
al.add(t);
t.start();
}
for( Thread t : al ) {
t.join();
}
}
catch( Exception e ) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
SynchronFinal:这与SynchronVolatile.java相同,除了它使用Object o的final,而不是volatile.
SynchronThis.java:
import java.io.*;
import java.util.*;
public class SynchronThis implements Runnable {
static int a;
static volatile Object o = new Object();
public void adder() {
synchronized( this ) {
SynchronThis.a++;
}
System.out.println( SynchronThis.a );
}
public void run() {
while( SynchronThis.a < 65535 ) {
adder();
}
}
public static void main( String []args ) {
ArrayList <Thread>al = new ArrayList<Thread>();
try {
int i;
for( i = 0; i<10 ; i++ ) {
SynchronThis s = new SynchronThis();
Thread t = new Thread( s );
al.add(t);
t.start();
}
for( Thread t : al ) {
t.join();
}
}
catch( Exception e ) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
SynchronA.java:
import java.io.*;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SynchronA implements Runnable {
static int a;
private volatile Lock lock = new ReentrantLock();
public void adder() {
lock.lock();
SynchronA.a++;
System.out.println( SynchronA.a );
lock.unlock();
}
public void run() {
while( SynchronA.a < 65535 ) {
adder();
}
}
public static void main( String []args ) {
ArrayList <Thread>al = new ArrayList<Thread>();
try {
int i;
for( i = 0; i<10 ; i++ ) {
SynchronA s = new SynchronA();
Thread t = new Thread( s );
al.add(t);
t.start();
}
for( Thread t : al ) {
t.join();
}
}
catch( Exception e ) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
SynchronObj.java:
import java.io.*;
import java.util.*;
public class SynchronObj implements Runnable {
static int a;
Object o;
public SynchronObj( Object obj ) {
o = obj;
}
public void adder() {
synchronized( o ) {
SynchronObj.a++;
}
System.out.println( SynchronObj.a );
}
public void run() {
while( SynchronObj.a < 65535 ) {
adder();
}
}
public static void main( String []args ) {
ArrayList <Thread>al = new ArrayList<Thread>();
final Object o = new Object();
try {
int i;
for( i = 0; i<10 ; i++ ) {
SynchronObj s = new SynchronObj( o );
Thread t = new Thread( s );
al.add(t);
t.start();
}
for( Thread t : al ) {
t.join();
}
}
catch( Exception e ) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
当它运行时,上面的线程同步方法都没有100%的时间工作.什么可能出错?
您的问题是,在某些情况下,您的锁定锁定在不同的锁定对象实例上,因此它们实际上从不干扰其他锁定.
更改
Object o;
Run Code Online (Sandbox Code Playgroud)
至
public static final Object o = new Object();
Run Code Online (Sandbox Code Playgroud)
现在,您的所有synchronized语句都将尝试锁定同一个对象,并且将发生正确的锁争用.
这看起来很可疑:
while (SynchronObj.a < 65535) {...}
Run Code Online (Sandbox Code Playgroud)
因为你正在读取没有同步的a的值.绝对是一个问题.
您的同步测试方法似乎也是通过搜索打印的重复输出.相反,尝试做
public void run() {
for (int i=0; i<10000; i++) {
adder();
}
}
Run Code Online (Sandbox Code Playgroud)
因为您正在运行10个线程,所以只需验证最终答案是否正确10000*10.任何更少/更多将暗示不正确的线程同步.
| 归档时间: |
|
| 查看次数: |
123 次 |
| 最近记录: |