1. 读写锁的合理运用
- 原理:读写锁允许多个线程同时进行读操作,但只允许一个线程进行写操作。当有写操作时,所有读操作和其他写操作都会被阻塞,这样可以保证数据的一致性,同时在读多写少的场景下能显著提升性能。
- 示例(以Python为例):
import threading
class Data:
def __init__(self):
self.value = 0
self.lock = threading.RLock()
self.read_lock = threading.Semaphore(1)
self.write_lock = threading.Semaphore(1)
def read(self):
self.read_lock.acquire()
self.lock.acquire()
try:
return self.value
finally:
self.lock.release()
self.read_lock.release()
def write(self, new_value):
self.write_lock.acquire()
self.lock.acquire()
try:
self.value = new_value
finally:
self.lock.release()
self.write_lock.release()
data = Data()
def reader_thread():
for _ in range(1000):
result = data.read()
# 处理读取到的数据
pass
def writer_thread():
for _ in range(100):
data.write(_)
readers = [threading.Thread(target=reader_thread) for _ in range(10)]
writers = [threading.Thread(target=writer_thread) for _ in range(2)]
for reader in readers:
reader.start()
for writer in writers:
writer.start()
for reader in readers:
reader.join()
for writer in writers:
writer.join()
2. 减少锁的粒度
- 原理:将大的共享数据结构分解为多个小的部分,每个部分使用单独的锁进行保护。这样不同线程可以同时访问不同部分的数据,减少锁竞争。
- 示例(以Java为例):
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class FineGrainedLocking {
private final Lock[] locks;
private final int[] data;
public FineGrainedLocking(int size) {
locks = new Lock[size];
data = new int[size];
for (int i = 0; i < size; i++) {
locks[i] = new ReentrantLock();
}
}
public void update(int index, int value) {
locks[index].lock();
try {
data[index] = value;
} finally {
locks[index].unlock();
}
}
public int read(int index) {
locks[index].lock();
try {
return data[index];
} finally {
locks[index].unlock();
}
}
}
3. 锁的分层
- 原理:对于复杂的数据结构,可以采用锁分层的方式。例如,对于树形结构,可以对每个节点设置锁,并且父节点的锁可以覆盖子节点的锁。这样在进行某些操作时,可以只获取父节点的锁,而不是获取所有子节点的锁,从而减少锁的范围。
- 示例(以C++为例,简单模拟树形结构锁分层):
#include <mutex>
#include <vector>
class TreeNode {
public:
std::mutex nodeLock;
std::vector<TreeNode*> children;
int data;
TreeNode(int value) : data(value) {}
void updateData(int newData) {
std::lock_guard<std::mutex> lock(nodeLock);
data = newData;
}
int getData() {
std::lock_guard<std::mutex> lock(nodeLock);
return data;
}
};
class Tree {
public:
TreeNode* root;
std::mutex rootLock;
Tree(int rootValue) {
root = new TreeNode(rootValue);
}
void updateRootData(int newData) {
std::lock_guard<std::mutex> lock(rootLock);
root->updateData(newData);
}
int getRootData() {
std::lock_guard<std::mutex> lock(rootLock);
return root->getData();
}
};
4. 乐观锁
- 原理:乐观锁假设在大多数情况下,线程不会发生冲突,因此在进行数据操作时,不会像互斥锁那样一开始就加锁。而是在更新数据的时候,检查数据在操作过程中是否被其他线程修改过,如果没有被修改过,则执行更新操作,否则重试。
- 示例(以Python为例,使用版本号实现乐观锁):
class OptimisticLocking:
def __init__(self):
self.value = 0
self.version = 0
def update(self, new_value):
while True:
current_version = self.version
current_value = self.value
# 模拟业务逻辑
new_result = current_value + new_value
if self.version == current_version:
self.value = new_result
self.version += 1
return