前言
首页 > 数据库 > 数据库开发技术 > 并发编程的艺术07-非阻塞同步演进

前言
粗粒度同步




public class CoarseList<T> {private class Node {T item;int key;Node next;Node(T item) {this.item = item;this.key = item.hashCode();}Node(int key) {this.item = null;this.key = key;}}private Node head = new Node(Integer.MIN_VALUE);private Node tail = new Node(Integer.MAX_VALUE);private Lock lock = new ReentrantLock();public CoarseList() {head.next = this.tail;}public boolean add(T item) {Node pred, curr;int key = item.hashCode();lock.lock();try {pred = head;curr = pred.next;while (curr.key < key) {pred = curr;curr = curr.next;}if (key == curr.key) {return false;} else {Node node = new Node(item);node.next = curr;pred.next = node;return true;}} finally {lock.unlock();}}public boolean remove(T item) {Node pred, curr;int key = item.hashCode();lock.lock();try {pred = this.head;curr = pred.next;while (curr.key < key) {pred = curr;curr = curr.next;}if (key == curr.key) {pred.next = curr.next;return true;} else {return false;}} finally {lock.unlock();}}public boolean contains(T item) {Node pred, curr;int key = item.hashCode();lock.lock();try {pred = head;curr = pred.next;while (curr.key < key) {pred = curr;curr = curr.next;}return (key == curr.key);} finally {lock.unlock();}}}


细粒度同步

public class FineList<T> {private class Node {T item;int key;Node next;Lock lock;Node(T item) {this.item = item;this.key = item.hashCode();this.lock = new ReentrantLock();}Node(int key) {this.item = null;this.key = key;this.lock = new ReentrantLock();}void lock() {lock.lock();}void unlock() {lock.unlock();}}private Node head = new Node(Integer.MIN_VALUE);public FineList() {head.next = new Node(Integer.MAX_VALUE);}public boolean add(T item) {int key = item.hashCode();head.lock();Node pred = head;try {Node curr = pred.next;curr.lock();try {while (curr.key < key) {pred.unlock();pred = curr;curr = curr.next;curr.lock();}if (curr.key == key) {return false;}Node newNode = new Node(item);newNode.next = curr;pred.next = newNode;return true;} finally {curr.unlock();}} finally {pred.unlock();}}public boolean remove(T item) {Node pred = null, curr = null;int key = item.hashCode();head.lock();try {pred = head;curr = pred.next;curr.lock();try {while (curr.key < key) {pred.unlock();pred = curr;curr = curr.next;curr.lock();}if (curr.key == key) {pred.next = curr.next;return true;}return false;} finally {curr.unlock();}} finally {pred.unlock();}}public boolean contains(T item) {Node last = null, pred = null, curr = null;int key = item.hashCode();head.lock();try {pred = head;curr = pred.next;curr.lock();try {while (curr.key < key) {pred.unlock();pred = curr;curr = curr.next;curr.lock();}return (curr.key == key);} finally {curr.unlock();}} finally {pred.unlock();}}}
乐观同步
public class OptimisticList<T> {private class Node {T item;int key;Node next;Lock lock;Node(T item) {this.item = item;this.key = item.hashCode();this.lock = new ReentrantLock();}Node(int key) {this.item = null;this.key = key;this.lock = new ReentrantLock();}void lock() {lock.lock();}void unlock() {lock.unlock();}}private Node head = new Node(Integer.MIN_VALUE);public OptimisticList() {head.next = new Node(Integer.MAX_VALUE);}public boolean add(T item) {int key = item.hashCode();while (true) {Node pred = this.head;Node curr = pred.next;while (curr.key <= key) {pred = curr; curr = curr.next;}pred.lock(); curr.lock();try {if (validate(pred, curr)) {if (curr.key == key) {return false;} else {Entry entry = new Entry(item);entry.next = curr;pred.next = entry;return true;}}} finally {pred.unlock(); curr.unlock();}}}public boolean remove(T item) {int key = item.hashCode();while (true) {Node pred = this.head;Node curr = pred.next;while (curr.key < key) {pred = curr; curr = curr.next;}pred.lock(); curr.lock();try {if (validate(pred, curr)) {if (curr.key == key) {pred.next = curr.next;return true;} else {return false;}}} finally {pred.unlock(); curr.unlock();}}}public boolean contains(T item) {int key = item.hashCode();while (true) {Node pred = this.head;Node curr = pred.next;while (curr.key < key) {pred = curr; curr = curr.next;}try {pred.lock(); curr.lock();if (validate(pred, curr)) {return (curr.key == key);}} finally {pred.unlock(); curr.unlock();}}}private boolean validate(Node pred, Node curr) {Node node = head;while (node.key <= pred.key) {if (node == pred)return pred.next == curr;node = node.next;}return false;}}
惰性同步
public class LazyList<T> {private class Node {T item;int key;Node next;Lock lock;boolean marked;Node(T item) {this.item = item;this.key = item.hashCode();this.lock = new ReentrantLock();this.marked = false;}Node(int key) {this.item = null;this.key = key;this.lock = new ReentrantLock();this.marked = false;}void lock() {lock.lock();}void unlock() {lock.unlock();}}public boolean add(T item) {int key = item.hashCode();while (true) {Node pred = this.head;Node curr = head.next;while (curr.key < key) {pred = curr; curr = curr.next;}pred.lock();try {curr.lock();try {if (validate(pred, curr)) {if (curr.key == key) {return false;} else {Node node = new Node(item);node.next = curr;pred.next = node;return true;}}} finally {curr.unlock();}} finally {pred.unlock();}}}public boolean remove(T item) {int key = item.hashCode();while (true) {Node pred = this.head;Node curr = head.next;while (curr.key < key) {pred = curr; curr = curr.next;}pred.lock();try {curr.lock();try {if (validate(pred, curr)) {if (curr.key != key) {return false;} else {curr.marked = true;pred.next = curr.next;return true;}}} finally {curr.unlock();}} finally {pred.unlock();}}}public boolean contains(T item) {int key = item.hashCode();Node curr = this.head;while (curr.key < key)curr = curr.next;return curr.key == key && !curr.marked;}private boolean validate(Node pred, Node curr) {return !pred.marked && !curr.marked && pred.next == curr;}}
非阻塞同步




public class LockFreeList<T> {private class Node {T item;int key;AtomicMarkableReference<Node> next;Node(T item) {this.item = item;this.key = item.hashCode();this.next = new AtomicMarkableReference<Node>(null, false);}Node(int key) { // sentinel constructorthis.item = null;this.key = key;this.next = new AtomicMarkableReference<Node>(null, false);}}class Window {public Node pred;public Node curr;Window(Node pred, Node curr) {this.pred = pred; this.curr = curr;}}Node head;public LockFreeList() {this.head = new Node(Integer.MIN_VALUE);Node tail = new Node(Integer.MAX_VALUE);while (!head.next.compareAndSet(null, tail, false, false));}public boolean add(T item) {int key = item.hashCode();boolean splice;while (true) {Window window = find(head, key);Node pred = window.pred, curr = window.curr;if (curr.key == key) {return false;} else {// splice in new nodeNode node = new Node(item);node.next = new AtomicMarkableReference(curr, false);if (pred.next.compareAndSet(curr, node, false, false)) {return true;}}}}public boolean remove(T item) {int key = item.hashCode();boolean snip;while (true) {Window window = find(head, key);Node pred = window.pred, curr = window.curr;if (curr.key != key) {return false;} else {// snip out matching nodeNode succ = curr.next.getReference();snip = curr.next.attemptMark(succ, true);if (!snip)continue;pred.next.compareAndSet(curr, succ, false, false);return true;}}}public boolean contains(T item) {int key = item.hashCode();Node curr = this.head;while (curr.key < key)curr = curr.next;return curr.key == key && !curr.marked;}public Window find(Node head, int key) {Node pred = null, curr = null, succ = null;boolean[] marked = {false}; // is curr marked?boolean snip;retry: while (true) {pred = head;curr = pred.next.getReference();while (true) {succ = curr.next.get(marked);while (marked[0]) { // replace curr if markedsnip = pred.next.compareAndSet(curr, succ, false, false);if (!snip) continue retry;curr = pred.next.getReference();succ = curr.next.get(marked);}if (curr.key >= key)return new Window(pred, curr);pred = curr;curr = succ;}}}}
通过基于链表的锁的发展变化,在这个演进过程中,锁的粒度和使用频率逐步减小,最后得到一个无阻塞的链表。从 LazyList 最终到 LockFreeList ,为并发程序设计者提供了一些直接可用的设计策略。像乐观同步和惰性同步这样的一些方法,在设计更为复杂的数据结构时也经常用到。
一方面 LockFreeList 算法能够保证在面对任意的延迟时,线程可以继续演进。当然,这种强演进保证需要一些代价:

到这里今天的内容就讲完了,希望对你有帮助,如果觉得有收获还请点击"再看"支持作者。本人才疏学浅,如果文中有不当之处还请留言指正。

往期精彩回顾
长按识别


原文作者:DevXTalk;如有侵权,请联系管理员删除。