62,616
社区成员
发帖
与我相关
我的任务
分享
private static Lock lock = new ReentrantLock();
private static int count = 0;
public static void main(String[] args) throws Exception {
for (int i = 0; i < 10000; i++) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(count);
lock.lock();
count = count + 1;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
}
});
t1.start();
}
}
[/quote]
JVM碰到unlock的时候,就会释放锁,在释放锁之前会把相关变量(堆里面的也包括方法区的静态量)写会相应的内存区,然后释放锁,之后别的线程就可以重新获得这块内存的锁了
非栈对象更新完了都会写回内存啊,只是这过程不确定顺序,加锁就是为了在别的线程访问这块内存之前不能访问,不过,共享锁好像是可以读的(但你仍然得获得这块内存相应的读锁),不能写,当然这个时候你读的就不一定准确了,所以如果要确保实时读取数据正确的,还是不要共享锁
我的个人理解[/quote]
错了,非栈对象要等跳出栈帧才写回去的吧,而锁呢,应该是释放之前写会去的,要不然假如释放锁,但是方法没完(块锁),这对象的内存没锁,没写回去,锁就没意义了[/quote]
一帮傻x, 都没有明白题主的意思,我任务lock根本就没有保证可见性,只是实现了访问的原子性。要不并发库的源码里面也不会随处可见volatile了。[/quote]
同意楼上的看法,lock是用java代码实现的(concurrent包),不是jvm的内置关键字,lock只是保证操作的原子性,没有可见性的保证
private static Lock lock = new ReentrantLock();
private static int count = 0;
public static void main(String[] args) throws Exception {
for (int i = 0; i < 10000; i++) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(count);
lock.lock();
count = count + 1;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
}
});
t1.start();
}
}
[/quote]
JVM碰到unlock的时候,就会释放锁,在释放锁之前会把相关变量(堆里面的也包括方法区的静态量)写会相应的内存区,然后释放锁,之后别的线程就可以重新获得这块内存的锁了
非栈对象更新完了都会写回内存啊,只是这过程不确定顺序,加锁就是为了在别的线程访问这块内存之前不能访问,不过,共享锁好像是可以读的(但你仍然得获得这块内存相应的读锁),不能写,当然这个时候你读的就不一定准确了,所以如果要确保实时读取数据正确的,还是不要共享锁
我的个人理解[/quote]
错了,非栈对象要等跳出栈帧才写回去的吧,而锁呢,应该是释放之前写会去的,要不然假如释放锁,但是方法没完(块锁),这对象的内存没锁,没写回去,锁就没意义了[/quote]
一帮傻x, 都没有明白题主的意思,我任务lock根本就没有保证可见性,只是实现了访问的原子性。要不并发库的源码里面也不会随处可见volatile了。
private static Lock lock = new ReentrantLock();
private static int count = 0;
public static void main(String[] args) throws Exception {
for (int i = 0; i < 10000; i++) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(count);
lock.lock();
count = count + 1;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
}
});
t1.start();
}
}
[/quote]
JVM碰到unlock的时候,就会释放锁,在释放锁之前会把相关变量(堆里面的也包括方法区的静态量)写会相应的内存区,然后释放锁,之后别的线程就可以重新获得这块内存的锁了
非栈对象更新完了都会写回内存啊,只是这过程不确定顺序,加锁就是为了在别的线程访问这块内存之前不能访问,不过,共享锁好像是可以读的(但你仍然得获得这块内存相应的读锁),不能写,当然这个时候你读的就不一定准确了,所以如果要确保实时读取数据正确的,还是不要共享锁
我的个人理解[/quote]
错了,非栈对象要等跳出栈帧才写回去的吧,而锁呢,应该是释放之前写会去的,要不然假如释放锁,但是方法没完(块锁),这对象的内存没锁,没写回去,锁就没意义了
private static Lock lock = new ReentrantLock();
private static int count = 0;
public static void main(String[] args) throws Exception {
for (int i = 0; i < 10000; i++) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(count);
lock.lock();
count = count + 1;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
}
});
t1.start();
}
}
[/quote]
JVM碰到unlock的时候,就会释放锁,在释放锁之前会把相关变量(堆里面的也包括方法区的静态量)写会相应的内存区,然后释放锁,之后别的线程就可以重新获得这块内存的锁了
非栈对象更新完了都会写回内存啊,只是这过程不确定顺序,加锁就是为了在别的线程访问这块内存之前不能访问,不过,共享锁好像是可以读的(但你仍然得获得这块内存相应的读锁),不能写,当然这个时候你读的就不一定准确了,所以如果要确保实时读取数据正确的,还是不要共享锁
我的个人理解
private static Lock lock = new ReentrantLock();
private static int count = 0;
public static void main(String[] args) throws Exception {
for (int i = 0; i < 10000; i++) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(count);
lock.lock();
count = count + 1;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
}
});
t1.start();
}
}
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
这样的实现难道不是只有虚拟机才能完成吗。。
类似可见性的事情也只有通过这样的native方法才能完成了。。
难道你会以为java代码能完成这样的功能。。
这个类的实现可没有使用synchronized。。
至于在虚拟机内部怎么实现,还需要去翻翻虚拟机的书。。