开始我们的Semaphore项目,我给了我的学生一个糟糕的p()方法版本:
proc p() {
while (this.tokens <= 0) {
sleep(1);
writeln("Tokens: ", this.tokens);
}
this.tokens -= 1;
}
Run Code Online (Sandbox Code Playgroud)
我给它们一些额外的代码来测试它,它增加了另一个线程中的令牌数量(使用v()方法).您可以看到令牌数量增加(大于0)但代码不会退出while循环.
一时兴起,我添加了一个任务声明:
proc p() {
while (this.tokens <= 0) {
this.tokens = this.tokens;
sleep(1);
writeln("Tokens: ", this.tokens);
}
this.tokens -= 1;
}
Run Code Online (Sandbox Code Playgroud)
这解决了测试运行中的问题(尽管它的线程安全性更低).为什么原始的while循环卡住了,为什么添加这个赋值可以解决它?
去年问题的解决方案是使我的实例变量为atomics,以确保其他任务可以看到它们的变化.(虽然方法中的循环卡住了.添加字段赋值给自己修复了问题)
今年我用初始化器替换我的构造函数.(https://chapel-lang.org/docs/master/language/evolution.html#readme-evolution-initializers-replace-constructors)不幸的是,我不知道如何初始化原子实例变量.此代码不起作用:
class FakeSemaphore {
var tokens : atomic int;
proc init(initTokens : int) {
this.tokens.write(initTokens);
}
}
Run Code Online (Sandbox Code Playgroud)
这导致教堂1.18中的以下内容:
$ chpl FakeSemaphore.chpl
FakeSemaphore.chpl:4: In initializer:
FakeSemaphore.chpl:5: error: field "tokens" used before it is initialized
Run Code Online (Sandbox Code Playgroud)
我应该如何初始化我的原子实例变量?
用于init中创建的对象字段的适当所有权是什么?我认为最好使用“所有”,但看起来它在初始化完成后并没有保留那些。
运行此代码...(在线尝试!)
class Name {
var text : string;
//initializer
proc init(name : string) {
this.text = name;
}
proc writeThis(writer) {
writer.writeln(this.text);
}
} //end of Name
class Monkey {
var name : Name;
var age : int;
proc init(name : string, age : int) {
this.name = new owned Name(name);
this.age = age;
}
proc writeThis(writer) {
writer.writeln("I'm a monkey named ", this.name, ", and I'm ", this.age, " years old.");
}
} //end of class …Run Code Online (Sandbox Code Playgroud)