我碰巧发表了一篇文章,最近讨论了Java中的双重检查锁定模式及其陷阱,现在我想知道我多年来一直使用的那种模式的变体是否会受到任何问题的影响.
我已经查看了很多关于这个主题的帖子和文章,并了解了获取对部分构造对象的引用的潜在问题,据我所知,我认为我的实现不受这些问题的影响.以下模式是否有任何问题?
而且,如果没有,为什么人们不使用它?我在这个问题的任何讨论中都没有看过它.
public class Test {
private static Test instance;
private static boolean initialized = false;
public static Test getInstance() {
if (!initialized) {
synchronized (Test.class) {
if (!initialized) {
instance = new Test();
initialized = true;
}
}
}
return instance;
}
}
Run Code Online (Sandbox Code Playgroud) java singleton multithreading synchronization double-checked-locking
我被要求描述这些代码行正在为大学作业做些什么
int main() {
int t1[] = {0,0,1,1,1}, t2[] = {0,0,1,1,1};
int *p1 = t1, *p2 = t2;
while (!*p1++ || !*p2++);
cout << (p1-t1) << endl;
cout << (p2-t2) << endl;
}
Run Code Online (Sandbox Code Playgroud)
我的看法是,创建了2个int类型的数组并填充了值,创建了2个指针并指向每个数组,然后我开始遇到麻烦.
while (!*p1++ || !*p2++);
Run Code Online (Sandbox Code Playgroud)
对我来说这是说在0移动*p1一个地方的位置或0移动*p2一个地方的位置时,我对这个假设真的没有信心吗?
cout << (p1-t1) << endl;
Run Code Online (Sandbox Code Playgroud)
那么我们继续前进cout,现在我对此的看法是,我正在从位置减去p1位置t1,在那里p1被while定位并t1指向数组中的第一个位置.我可能完全错了,我只是在学习指针,所以如果我的假设错了,请记住这一点.
最近我看到一些C#项目使用双重检查锁定模式Dictionary.像这样的东西:
private static readonly object _lock = new object();
private static volatile IDictionary<string, object> _cache =
new Dictionary<string, object>();
public static object Create(string key)
{
object val;
if (!_cache.TryGetValue(key, out val))
{
lock (_lock)
{
if (!_cache.TryGetValue(key, out val))
{
val = new object(); // factory construction based on key here.
_cache.Add(key, val);
}
}
}
return val;
}
Run Code Online (Sandbox Code Playgroud)
这段代码是不正确的,因为当(在锁外)迭代Dictionary集合时,可以"增长" 集合.在许多情况下这可能是极不可能的,但仍然是错误的._cache.Add()_cache.TryGetValue
是否有一个简单的程序来证明此代码失败了?
将其纳入单元测试是否有意义?如果是这样,怎么样?
我正在阅读这篇关于"双重检查锁定"的文章,并且在文章的主题之外我想知道为什么在文章的某些方面作者使用下一个成语:
清单7.尝试解决乱序写入问题
Run Code Online (Sandbox Code Playgroud)public static Singleton getInstance() { if (instance == null) { synchronized(Singleton.class) { //1 Singleton inst = instance; //2 if (inst == null) { synchronized(Singleton.class) { //3 inst = new Singleton(); //4 } instance = inst; //5 } } } return instance; }
我的问题是:有没有理由用同一个锁同步两次代码?有这个任何目的吗?
提前谢谢了.
假设我们给出了一个整数输入数组,如何找到满足以下条件的最长凸子序列:
c[i] < (c[i-1] + c[i+1]) / 2
Run Code Online (Sandbox Code Playgroud)
c[i-1],c[i]并且c[i+1]是子序列中的三个连续元素.
例如,如果输入数组是{ 1, 2, -1, 0, 3, 8, 5 },则最长的凸子序列应为:{ 1, -1, 0, 3, 8 }或{ 2, -1, 0, 3, 8 }.
我试图在"最长增加子序列"(LIS)问题中使用相同的动态编程思想来解决这个问题.但是因为子序列中的每个元素都依赖于前两个元素,所以似乎O(n ^ 2)解决方案是不可能的.谢谢您的帮助.
为什么会这样?
错误:命名空间'std'中没有名为'vector'的类型; 你是说'百科'吗?void askForVector(std :: vector*vector);
#include <iostream>
#include <vector>
void askForVector(std::vector * vector);
int main()
{
std::vector<int> vector;
int size;
askForVector(&vector);
std::cout << "\nsize: " << vector.size() << std::endl;
std::cout << vector.at(0);
}
void askForVector(std::vector * vector)
{
int size;
std::cout << "please insert the size of vector to order: ";
std::cin >> size;
vector->resize(size);
for(int i = 0; i<size; i++){
std::cout << "please insert a value for the " << i+1 << " position: " ;
std::cin >> …Run Code Online (Sandbox Code Playgroud) 我在Mike Ash的"照顾和喂养单身人士"中遇到了这个问题,他的评论有点困惑:
不过,这段代码有点慢.拿锁是有点贵的.令人痛苦的是,在绝大多数情况下,锁定毫无意义.只有当foo为nil时才需要锁定,这基本上只发生一次.在单例初始化之后,对锁的需求消失了,但锁本身仍然存在.
+(id)sharedFoo {
static Foo *foo = nil;
@synchronized([Foo class]) {
if(!foo) foo = [[self alloc] init];
}
return foo;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,毫无疑问这是一个很好的理由,但为什么你不能写(见下文)来限制当foo为零时的锁定?
+(id)sharedFoo {
static Foo *foo = nil;
if(!foo) {
@synchronized([Foo class]) {
foo = [[self alloc] init];
}
}
return foo;
}
Run Code Online (Sandbox Code Playgroud)
欢呼加里
最近我被问到一个问题,实现一个非常简单的malloc具有以下限制和初始条件.
#define HEAP_SIZE 2048
int main()
{
privateHeap = malloc(HEAP_SIZE + 256); //extra 256 bytes for heap metadata
void* ptr = mymalloc( size_t(750) );
myfree( ptr );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我需要实现mymalloc并myfree在这里使用提供的确切空间.256字节很好地映射到2048位,如果分配了一个字节或者它是空闲的,我可以存储一个位数组.但是当我myfree打电话时ptr,我不知道开始时分配了多少大小.我不能使用任何额外的位.
我似乎认为没有办法解决这个问题,但我一直在重申可以做到这一点.有什么建议 ?
mallocs和释放来测试它,它没有任何小的内存块.但这并不保证任何事情.文档中的指南:关于代码的某些指南:
mymalloc,myrealloc,myFree为所有可能的输入工作.myrealloc应该像realloc在C++库中
一样执行以下操作void* myrealloc( void* C, size_t newSize ):
newSize大于块中的大小reallocThis:
newSize以便新的块的基指针也是 …我有一个矢量类:
class Vector:
def __init__(self, x, y):
self.x, self.y = x, y
def __str__(self):
return '(%s,%s)' % (self.x, self.y)
def __add__(self, n):
if isinstance(n, (int, long, float)):
return Vector(self.x+n, self.y+n)
elif isinstance(n, Vector):
return Vector(self.x+n.x, self.y+n.y)
Run Code Online (Sandbox Code Playgroud)
哪个工作正常,即我可以写:
a = Vector(1,2)
print(a + 1) # prints (2,3)
Run Code Online (Sandbox Code Playgroud)
但是,如果操作顺序颠倒,则失败:
a = Vector(1,2)
print(1 + a) # raises TypeError: unsupported operand type(s)
# for +: 'int' and 'instance'
Run Code Online (Sandbox Code Playgroud)
我理解错误:一个的加入int对象的Vector,因为我没有在定义它的对象是未定义int类.有没有办法解决这个问题而不在类int(或父int类)中定义它?
考虑"对实例字段的延迟初始化进行双重检查":
// Item 71 in Effective Java copied from this interview with Bloch. private volatile FieldType field; FieldType getField() { FieldType result = field; if (result == null) { // First check (no locking) synchronized(this) { result = field; if (result == null) // Second check (with locking) field = result = computeFieldValue(); } } return result; }
我希望能够以安全的方式重置字段(强制它再次从数据库加载,在我的情况下).我假设我们可以通过重置方法来做到这一点:
void reset() {
field = null;
}
这是重置场地的标准方法吗?安全吗?任何陷阱?我问,因为布洛赫发出了关于双重检查懒惰加载的以下警告:"成语非常快,但也很复杂和细腻,所以不要试图以任何方式修改它.只需复制和粘贴 - 通常这不是一个好主意,但在这里是合适的."
在此先感谢喜马拉雅山脉的Playa.