Mat*_*toy 3 java junit multithreading synchronization thread-safety
我有这个我建立的singelton数据库,以及我创建的这个Junit测试:
独生子
package SingeltonDBVersion1;
import GlobalSetting.User;
/****************************************************************************
* This is the SingeltonDB. it warps the object DBconn according to the
* Singleton pattern. it receive name and password (i.e. DBConn parameters) and
* if it is the first time that a UserContorll try to get an instance it connect
* to the database. After that, the DBConn instance will be return to the user.
*****************************************************************************/
public class SingeltonDB {
private static DBconnImpl db = null;
private static SingeltonDB singalDb = null;
boolean first = true;
private SingeltonDB(String username, String password) {
if (first) {
try {
System.out.println("first");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
first = false;
}
db = new DBconnImpl();
}
public static SingeltonDB getInstance(String username, String password)
throws Exception {
if (db != null) {
return singalDb;
}
singalDb = new SingeltonDB(username, password);
System.out.println("The database is now open");
db.connect(username, password);
System.out.println("The database was connected");
return singalDb;
}
public void create(String tableName) throws Exception {
db.create(tableName);
}
public User query(String tableName, int userID) throws Exception {
if (db == null) {
System.out.println("Error: the database is not open");
return null;
}
return (db.query(tableName, userID));
}
public void update(String tableName, User user) throws Exception {
if (db == null) {
System.out.println("Error: the database is not open");
return;
}
db.update(tableName, user);
}
public void disconnect() throws Exception {
db.disconnect();
}
public static void reset() throws Exception {
db = null;
}
}
Run Code Online (Sandbox Code Playgroud)
Junit的
package Tests;
import java.util.concurrent.CountDownLatch;
import org.junit.Test;
import SingeltonDBVersion1.SingeltonDB;
public class SingeltonDBVersion1Tests {
@Test
public synchronized void testSynch() throws Exception {
int num=2;
CountDownLatch doneSignal = new CountDownLatch(num);
MySingeltonDB[] instances = new MySingeltonDB[num];
for (int i = 0; i < num; i++) {
instances[i]=new MySingeltonDB(doneSignal);
}
SingeltonDB.reset();
for (int i = 0; i < num; i++) {
instances[i].run();
}
doneSignal.await();
for (int i = 0; i < num; i++) {
for (int j = i; j < instances.length; j++) {
if (instances[i].getDB()!=instances[j].getDB())
{
throw (new Exception());
}
}
}
}
class MySingeltonDB implements Runnable {
SingeltonDB db;
CountDownLatch doneSignal;
public MySingeltonDB(CountDownLatch doneSignal) {
this.db = null;
this.doneSignal = doneSignal;
}
public SingeltonDB getDB() {
return db;
}
@Override
public void run() {
try {
this.db = SingeltonDB.getInstance("MyAccount", "123");
doneSignal.countDown();
System.out.println("----------------------------------------->"+db );
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我在这里要做的是创建2个单例实例,当且仅当singletonDB方法:getInstance()未同步时.但由于某种原因,即使我不在方法中使用synchronized,单例也能正常工作并返回该类的一个实例.
尝试我的测试,它重现了问题:
static class Singleton {
static Singleton i;
static Singleton getInstance() {
if (i == null) {
i = new Singleton();
}
return i;
}
}
public static void main(String[] args) throws Exception {
Callable<Singleton> c = new Callable<Singleton>() {
@Override
public Singleton call() throws Exception {
return Singleton.getInstance();
}
};
ExecutorService ex = Executors.newFixedThreadPool(2);
for(;;) {
Future<Singleton> f1 = ex.submit(c);
Future<Singleton> f2 = ex.submit(c);
if (f1.get() != f2.get()) {
System.out.println("!!!");
}
Singleton.i = null;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1424 次 |
| 最近记录: |