- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
在 iOS 的 objective-c 中同步对实例变量的读/写访问的最佳方式/最少等待的方式是什么?
变量被频繁读写(假设每秒读写 1000 次)。更改是否立即生效并不重要。读取获得彼此一致的数据甚至都不重要,但写入迟早必须反射(reflect)在读取获取的数据中。是否有一些数据结构允许这样做?
我想到了这个:
v[0]
和 v[1]
。v[i]
,创建一个并发调度队列来构造一个readers-writer-locking围绕它的机制。我们称它们为 q[i]
。v[0]
被写入,遵守 q[0]
的锁定机制。v[1]
被读取并且只有在一定的机会下,例如1%,读取操作查看 v[0]
并在必要时更新 v[1]
。下面的伪代码说明了这一点:
typedef int VType; // the type of the variable
VType* v; // array of first and second variable
dispatch_queue_t* q; // queues for synchronizing access to v[i]
- (void) setV:(VType)newV {
[self setV:newV at:0];
}
- (void) setV:(VType)newV at:(int)i {
dispatch_barrier_async(q[i], ^{
v[i] = newV;
});
}
- (VType) getV:(int)i {
__block VType result;
dispatch_sync(q[i], ^{
result = v[i];
});
return result;
}
- (VType) getV {
VType result = [self getV:1];
if ([self random] < 0.01) {
VType v0_result = [self getV:0];
if (v0_result != result) {
[self setV:v0_result at:1];
result = v0_result;
}
}
return result;
}
- (float) random {
// some random number generator - fast, but not necessarily good
}
这有以下好处:
v[0]
通常不会被读取操作占用。因此,写入操作通常不会阻塞。
在大多数情况下,v[1]
不会被写入,因此对此的读取操作通常不会阻塞。
不过,如果发生许多读取操作,写入的值最终会从 v[0]
传播到 v[1]
。可能会遗漏一些值,但这对我的应用程序无关紧要。
你们怎么看,这行得通吗?有更好的解决方案吗?
更新:
一些性能benchmarking(一次一个benchmark的读写尽可能快地并发完成1秒,一个读队列,一个写队列):
在装有 iOS 7 的 iPhone 4S 上:
runMissingSyncBenchmark: 484759 w/s
runMissingSyncBenchmark: 489558 r/s
runConcurrentQueueRWSyncBenchmark: 2303 w/s
runConcurrentQueueRWSyncBenchmark: 2303 r/s
runAtomicPropertyBenchmark: 460479 w/s
runAtomicPropertyBenchmark: 462145 r/s
在 iOS 7 的模拟器中:
runMissingSyncBenchmark: 16303208 w/s
runMissingSyncBenchmark: 12239070 r/s
runConcurrentQueueRWSyncBenchmark: 2616 w/s
runConcurrentQueueRWSyncBenchmark: 2615 r/s
runAtomicPropertyBenchmark: 4212703 w/s
runAtomicPropertyBenchmark: 4300656 r/s
到目前为止,原子属性获胜。非常。这是用 SInt64
测试的。
我预计并发队列的方法在性能上与原子属性相似,因为它是读写同步机制的标准方法。
当然,runMissingSyncBenchmark
有时会产生读取,表明 SInt64
的写入已完成一半。
最佳答案
也许,自旋锁
将是最佳选择(参见 man 3 自旋锁)。
由于可以测试自旋锁当前是否被锁定(这是一个快速操作),如果自旋锁被写入器任务持有,读取器任务可以只返回之前的值。
也就是说,读取器任务使用OSSpinLockTry()
并仅在可以获得锁时才检索实际值。否则,读取任务将使用之前的值。
writer 任务将分别使用OSSpinLockLock()
和OSSpinLockUnlock()
来自动更新值。
来自手册页:
NAME OSSpinLockTry, OSSpinLockLock, OSSpinLockUnlock -- atomic spin lock synchronization primitives
SYNOPSIS
#include <libkern/OSAtomic.h>
bool
OSSpinLockTry(OSSpinLock *lock);
void
OSSpinLockLock(OSSpinLock *lock);
void
OSSpinLockUnlock(OSSpinLock *lock);DESCRIPTION
Spin locks are a simple, fast, thread-safe synchronization primitive that is suitable in situations where contention is expected to be low. The spinlock operations use memory barriers to synchronize access to shared memory protected by the lock. Preemption is possible while the lock is held.
OSSpinLock
is an integer type. The convention is that unlocked is zero, and locked is nonzero. Locks must be naturally aligned and cannot be in cache-inhibited memory.
OSSpinLockLock()
will spin if the lock is already held, but employs various strategies to back off, making it immune to most priority-inversion livelocks. But because it can spin, it may be inefficient in some situations.
OSSpinLockTry()
immediately returns false if the lock was held, true if it took the lock. It does not spin.
OSSpinLockUnlock()
unconditionally unlocks the lock by zeroing it.RETURN VALUES
OSSpinLockTry()
returns true if it took the lock, false if the lock was already held.
关于ios - 在 iOS 中同步对实例变量的读/写访问以实现高性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20851332/
我在不同的硬件上测试 Cassandra 已经有一段时间了。 首先我有 2 个 CPU 和 6 GB RAM 然后我更改为 16 个 CPU 和 16 GB RAM(其中只有 6 GB 可供我的测试使
我只是想从二进制文件中读/写。我一直在关注 this教程,它的工作原理......除了它似乎正在将内容写入 txt 文件。我在测试的时候把文件命名为test.bin,但是记事本可以打开并正常显示,所以
我编写了一些简单的 Java 代码来从文本文件中读取字符串,将它们组合起来,然后将它们写回。 (有关输出没有变化的简化版本,请参见下面的片段) 问题是输入文件和输出文件中的特定字符(- 和 ...)是
我真的很感兴趣——你为什么要放 readln; 从键盘读取一些值到变量后的行?例如, repeat writeln('Make your choise'); read(CH); if (CH = '1
只要程序不允许同时写入存储在模块中的共享数据结构的相同元素,它是线程安全的吗?我知道这是一个菜鸟问题,但在任何地方都找不到明确解决的问题。情况如下: 在程序开始时,数据被初始化并存储在模块级可分配数组
我有一个数据结构,其操作可以归类为读取操作(例如查找)和写入操作(例如插入、删除)。这些操作应该同步,以便: 读操作不能在写操作执行时执行(除非在同一线程上),但是读操作可以与其他读操作并发执行。 在
我在Java套接字编程中有几个问题。 在读取客户端套接字中的输入流时,如果抛出IO异常;那么我们是否需要重新连接服务器套接字/再次初始化客户端套接字? 如果我们关闭输出流,它将关闭客户端套接字吗? 如
我正在尝试从客户端将结构写入带有套接字的服务器。 结构是: typedef struct R { int a; int b; double c; double d; double result[4];
我想知道是否可以通过 Javascript 从/向 Azure Active Directory 广告读取/写入数据。我读到 Azure 上有 REST 服务,但主要问题是生成与之通信的 token
我希望有人能提供完整的工作代码,允许在 Haskell 中执行以下操作: Read a very large sequence (more than 1 billion elements) of 32
我有一个任务是制作考试模拟器。我的意思是,在老师输入某些科目的分数后,学生输入他的名字、姓氏和出生,然后他决定学生是否通过科目。所以,我有一个问题,如何用新行写入文件文本并通过重写该文件来读取(逐行读
我需要编写巨大的文件(超过 100 万行)并将文件发送到另一台机器,我需要使用 Java BufferedReader 一次读取一行。 我使用的是 indetned Json 格式,但结果不太方便,
我在 Android 应用程序中有一个读写操作。在 onCreate 上,将读取文件并将其显示为编辑文本并且可以进行编辑。当按下保存按钮时,数据将被写入 onCreate 上读取的同一文件中。但我得到
我正在编写一个程序,该程序从一个文件读取输入,然后该程序将格式化数据并将其写入另一个文件。 输入文件: Christopher kardaras,10 N Brainard,Naperville,IL
我有一个 SCALA(+ JAVA) 代码,它以一定的速率读写。分析可以告诉我代码中每个方法的执行时间。如何衡量我的程序是否达到了最大效率?为了使我的代码优化,以便它以给定配置可能的最大速度读取。我知
嗨,我想知道如何访问 java/maven 中项目文件夹中的文件,我考虑过使用 src/main/resources,但有人告诉我,写入此目录中的文件是一个坏主意,并且应该只在项目的配置中使用,所以我
我想读\写一个具有以下结构的二进制文件: 该文件由“RECORDS”组成。每个“RECORD”具有以下结构:我将以第一条记录为例 (红色)起始字节:0x5A(始终为 1 字节,固定值 0x5A) (绿
我想制作一个C程序,它将用一些参数来调用;每个参数将代表一个文件名,我想在每个参数中写一些东西。 FILE * h0; h0 = fopen(argv[0],"w"); char buff
我有一个包含团队详细信息的文件。我需要代码来读取文件,并将获胜百分比写入第二个文件。我还需要使用指示的搜索功能来搜索团队的具体信息。该代码未写入百分比文件。当菜单显示时,第一个文件的内容被打印,但代码
我正在使用 read() 和 write() 函数来处理我的类,并且我正在尝试使用一个函数来写入它所读取的内容以及我作为参数给出的前面的内容。 例如,我想给出 10 作为我的程序的参数 int mai
我是一名优秀的程序员,十分优秀!