通过java锁定数组中的每个项
假设我们有这些类:通过java锁定数组中的每个项,java,locking,synchronized,unlock,Java,Locking,Synchronized,Unlock,假设我们有这些类: 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 f
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);
}
}
在setValueByID方法完成之前,密钥-值对(记录)被锁定(无法从其他事务读取/写入)
int getValueByID(int key)
键值对(记录)被锁定,直到事务提交
void commit()
它解锁当前事务中锁定的所有键值对(记录)
因此,我的实现是:
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这种同步是使用带有某种锁的
wait()/notify()
方法实现的。阅读关于它们的Java教程(以及其他同步概念)。理想情况下,您需要熟悉Java并发包的ReadWriteLocksetValueId
应获得写锁并将其保持到事务提交getValueId
只需要一个读锁,该读锁可以被其他读锁共享,并在方法结束时释放
还要考虑一些超时,以便锁不会无限期地保持
研究:
- 读/写锁定模式
- 数据库系统中的隔离级别
- 交易处理
- 您不能使用同步块来实现它,而是需要使用锁之类的东西
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();
}
}
public Main{
公共静态void main(字符串[]args){
最终事务T=新事务();
对于(int n=0;n<10;n++){
新线程(newrunnable()){
公开募捐{
对于(int i=0;i<1000;i++){
T.setValueByID(i%100,i);
T.getValueByID(i%100);
如果(i%20==0)T.commit();
}
}
}).start();
}
}
}
类表{
静态最终记录[]表=新记录[100];
静态最终ReentrantLock[]锁=新的ReentrantLock[table.length];
静止的{
对于(int i=0;i
锁的问题是,在您的事务中,如果您在获得锁时不遵循命令,您可能会遇到死锁!此外,您需要确保正确处理异常,并始终通过调用commit()释放锁。我想问您另外一个问题……如何从事务类调用多线程?因为您没有编写“类事务扩展线程{}”对于所有这些问题,很抱歉……但我确实是线程初学者……如果可以给我一个简单的例子,说明如何创建单独的线程并从中调用事务方法……再次感谢您的帮助。@user1361554请检查编辑,它现在包含一个main()。如果我想让另一个线程读取第一条记录…我如何返回到该线程并使其运行调用commit()来释放lock@user1361554您可以随时从给定线程使用对T的引用调用commit。
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();
}
}