原子/易失性/同步如何在内部工作?
以下代码块之间有什么区别?
代码1
private int counter;
public int getNextUniqueIndex() {
return counter++;
}
Run Code Online (Sandbox Code Playgroud)
代码2
private AtomicInteger counter;
public int getNextUniqueIndex() {
return counter.getAndIncrement();
}
Run Code Online (Sandbox Code Playgroud)
代码3
private volatile int counter;
public int getNextUniqueIndex() {
return counter++;
}
Run Code Online (Sandbox Code Playgroud)
是否volatile以下列方式工作?是
volatile int i = 0;
void incIBy5() {
i += 5;
}
Run Code Online (Sandbox Code Playgroud)
相当于
Integer i = 5;
void incIBy5() {
int temp;
synchronized(i) { temp = i }
synchronized(i) { i = temp + 5 }
}
Run Code Online (Sandbox Code Playgroud)
我认为两个线程不能同时进入同步块...我是对的吗?如果这是真的那么如何atomic.incrementAndGet()工作没有synchronized …
我正在用java制作一个相互竞争的汽车程序.每辆车都是一个单独的线程.
当汽车完成比赛时,每个人都称这种方法.我已经在不同的计时器速度下测试了该方法,它似乎工作正常.但我确实意识到每个线程都在访问变量carsComplete,有时是在同一时间(至少在date命令给我的范围内).
所以我的问题是:这个方法是线程安全的吗?
public static String completeRace()
{
Date accessDate = new Date();
System.out.println("Cars Complete: " + carsComplete + " Accessed at " + accessDate.toString());
switch(++carsComplete)
{
case 1: return "1st";
case 2: return "2nd";
case 3: return "3rd";
default: return carsComplete + "th";
}
}
Run Code Online (Sandbox Code Playgroud) 我知道如果没有锁定,增量操作在C++中不是原子操作.
JVM是否会对其iinc指令实现添加任何锁定?
说我有这样一个方法:
synchronized void incrementIndex() {
index++;
}
Run Code Online (Sandbox Code Playgroud)
我想对这个方法进行单元测试,看看如果多个线程同时尝试增加索引,索引的最终值是否设置正确。假设我不知道方法声明中的“synchronized”关键字(并且我只知道方法的契约),我该如何进行测试?
ps 如果有帮助,我正在使用 Mockito 编写测试用例。
当我运行以下代码时,最终输出始终为正,如果我切换“x++”和“x--”的顺序,则最终输出始终为负。这个竞争条件的哪些部分被跳过是否有某种顺序?非常感谢任何帮助理解!
public class DataRace {
private static class MyThreadCode implements Runnable {
private static int x = 0; // NOTE THAT X IS STATIC!!!
@Override
public void run() {
for (int i = 0; i < 10000000; i++) {
x++;
x--;
}
System.out.println(x + " " + Thread.currentThread().getName());
}
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
Thread t = new Thread(new MyThreadCode());
t.start();
}
}
}
Run Code Online (Sandbox Code Playgroud) 我很好奇,如何在java8流中总结多个变量.
Integer wCPU = 0;
Double wnetwork = 0.0;
Double wMem = 0.0;
this.slaContractList.forEach(sla -> {
wCPU += sla.getNumberOfCPUs();
wnetwork += sla.getNetworkBandwith();
wMem += sla.getMemory();
});
Run Code Online (Sandbox Code Playgroud)
但是,这不会编译,因为lambda表达式中的变量应该是final.
如果int(整数)类型的变量在Java中具有固有的原子性,如下面的 Effective Java的摘录,那么为什么我们在示例中看到整数值的不一致状态:https: //docs.oracle.com/javase/tutorial/essential/concurrency /syncmeth.html
语言规范保证读取或写入变量是原子的,除非变量的类型为long或double [JLS,17.4.7].换句话说,读取long或double以外的变量可以保证返回某个线程存储到该变量中的值,即使多个线程同时修改变量而没有同步也是如此.
以上项目与我相矛盾.
我正在学习易变量.我知道volatile的作用,我为Volatile变量编写了一个示例程序,但没有按预期工作.
为什么"计数"的最终值有时会低于2000.我使用了volatile,因此系统不应该缓存"count"变量,值应该始终为2000.
当我使用synchronized方法时它工作正常但不是volatile关键字.
public class Worker {
private volatile int count = 0;
private int limit = 10000;
public static void main(String[] args) {
Worker worker = new Worker();
worker.doWork();
}
public void doWork() {
Thread thread1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < limit; i++) {
count++;
}
}
});
thread1.start();
Thread thread2 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < limit; …Run Code Online (Sandbox Code Playgroud) 我尝试使用 lambda 更改并获取局部变量。我知道我应该对 lambda 中的局部变量有效地使用final。当我使用 AtomicReference 局部变量更改失败时:
public class Lamb {
public static void main(String[] args) throws InterruptedException {
Lamb lamb = new Lamb();
GlobalL globalL = new GlobalL();
lamb.a(globalL);
for (int i = 0; i < 100; i++) {
new Thread(() -> {
globalL.printSum();
}).start();
}
Thread.sleep(3000);
System.out.println("--------After Work--------");
globalL.printSum();
}
public void a(GlobalL globalL) {
AtomicReference<Integer> number = new AtomicReference<>(0);
Work work = () -> {
number.getAndSet(number.get() + 1);
return number.get();
};
globalL.setWork(work);
} …Run Code Online (Sandbox Code Playgroud) 我需要这个可以访问相同数据的线程同时执行而不会相互混淆,所以Thread.join()我一直在尝试使用同步方法。问题是我根本看不到任何变化,它一直给我带来与使用它们之前相同的结果。我什至不知道我到底做错了什么,同步方法假设阻止其他同步方法在完成之前执行,对吗?希望你能给我一些关于正在发生的事情的线索。
public class ThreadSync{
public static void main(String[] args) throws InterruptedException {
//if execute properly
//output can't be other than 0
while(true) {
ChangeValue counter = new ChangeValue();
Threads t = new Threads(counter,"up");
Threads t2 = new Threads(counter,"down");
Threads t3 = new Threads(counter,"print");
t.start();
t2.start();
t3.start();
}
}
}
class Threads extends Thread{
Threads(ChangeValue obj, String act){
counter = obj;
action = act;
}
@Override
public void run() {
switch(action) {
case ("up"): counter.up(); break;
case ("down"): counter.down(); …Run Code Online (Sandbox Code Playgroud) 我只需要用java线程做一个竞争条件的例子,我写了这个代码,但我不确定它是否有竞争条件.
有人可以告诉我下面的代码是否有竞争条件,还有我如何改进或简化?
(抱歉英文不好)
public class RaceCondition extends Thread{
static int count=0; //the variable where the race condition need to happen
static int contador1 = 0; //variables to count
static int contador2 = 0;
static Thread t1 = new Thread(new Runnable() {
public void run(){
while(contador1!=20){
count ++;
System.out.print(count + " ");
contador1++;
}
}
});
static Thread t2 = new Thread(new Runnable() {
public void run(){
while(contador2!=20){
int k = 5;
count += 5*k;
System.out.print(count + " ");
contador2 ++; …Run Code Online (Sandbox Code Playgroud) 我读到,ConcurrentModificationException只要一个线程对某个列表执行结构修改,而另一个线程正在迭代其元素,则可以抛出 a 。为了检测此类修改,类的实例将List它们被修改的次数存储在名为 的字段中modCount,在列表的每次迭代时检查该字段的值以检查后者是否被修改。如果我的理解是正确的,则需要同步访问,因为如果在检查最后一次迭代中的值之后和循环结束之前modCount要修改所涉及的列表,则迭代器将无法检测到该列表是modCount在最后一次迭代期间进行了修改。
java ×12
concurrency ×3
atomic ×2
java-threads ×2
jvm ×2
atomicity ×1
collections ×1
java-8 ×1
java-stream ×1
lambda ×1
list ×1
static ×1
sum ×1
synchronized ×1
testing ×1
unit-testing ×1
volatile ×1