Art of Multiprocessor Programming 答案 ch11

本文探讨了在多核环境下,如何通过引入回退延迟策略减少共享栈的冲突,以及解决ABA问题和线程同步问题。讨论了如何在push和pop操作中避免数据丢失,以及如何在并发操作中确保数据一致性。
摘要由CSDN通过智能技术生成

126.

package p126;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class UnboundListStack
   
   
    
    
{
	public class Node
	{
		private T item;
		public Node next;
		
		public Node(T item)
		{
			this.item = item;
			this.next = null;
		}
		
		public T get()
		{
			return item;
		}
	}
	
	private Lock lock;
	private Node head;
	
	public UnboundListStack()
	{
		this.lock = new ReentrantLock();
		head = new Node(null);
	}
	
	public void push(T x)
	{
		Node node = new Node(x);
		
		lock.lock();
		
		try
		{
			node.next = head.next;
			head.next = node;
		}finally
		{
			lock.unlock();
		}
	}
	
	public T pop() throws Exception
	{
		lock.lock();
		
		try
		{
			if(head.next == null)
			{
				throw new Exception("Empty");
			}else
			{
				T item = head.next.get();
				head.next = head.next.next;
				return item;
			}
		}finally
		{
			lock.unlock();
		}
	}
	
}

   
   
127.

package p126;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class UnboundListStack
   
   
    
    
{
	public class Node
	{
		private T item;
		public Node next;
		
		public Node(T item)
		{
			this.item = item;
			this.next = null;
		}
		
		public T get()
		{
			return item;
		}
	}
	
	private Lock lock;
	private Node head;
	
	public UnboundListStack()
	{
		this.lock = new ReentrantLock();
		head = new Node(null);
	}
	
	public void push(T x)
	{
		Node node = new Node(x);
		
		lock.lock();
		
		try
		{
			node.next = head.next;
			head.next = node;
		}finally
		{
			lock.unlock();
		}
	}
	
	public T pop() throws Exception
	{
		lock.lock();
		
		try
		{
			if(head.next == null)
			{
				throw new Exception("Empty");
			}else
			{
				T item = head.next.get();
				head.next = head.next.next;
				return item;
			}
		}finally
		{
			lock.unlock();
		}
	}
	
}

   
   

128.

package p128;

import java.util.concurrent.atomic.AtomicStampedReference;

import utils.EmptyException;
import ch7.Backoff;

public class LockFreeStack
   
   
    
    
{
	public class Node
	{
		public T value;
		public Node next;
		public Node(T value)
		{
			this.value = value;
			next = null;
		}
	}
	
	static final int INITCAPACITY = 2;
	ThreadLocal
    
    
     
      nodeList = new ThreadLocal
     
     
      
      ()
	{
		protected Node initialValue()
		{
			Node head = new Node(null);
			
			for(int i = 0; i < INITCAPACITY; i ++)
			{
				Node node = new Node(null);
				node.next = head.next;
				head.next = node;
			}
			
			return head;
		}
	};
	
	private Node allocNode()
	{
		Node head = nodeList.get();
		if(head.next == null)
		{
			return new Node(null);
		}else
		{
			Node node = head.next;
			head.next = head.next.next;
			node.next = null;
			return node;
		}
	}
	
	private void freeNode(Node node)
	{
		if(node == null)
		{
			return;
		}
		node.value = null;
		Node head = nodeList.get();
		node.next = head.next;
		head.next = node;
	}
	
	AtomicStampedReference
      
      
       
        top = new AtomicStampedReference
       
       
         (null, 0); static final int MIN_DELAY = 1; static final int MAX_DELAY = 10; Backoff backoff = new Backoff(MIN_DELAY, MAX_DELAY); protected boolean tryPush(Node node) { int[] stamp = new int[1]; Node oldTop = top.get(stamp); node.next = oldTop; return (top.compareAndSet(oldTop, node, stamp[0], stamp[0] + 1)); } public void push(T value) { Node node = allocNode(); node.value = value; while(true) { if(tryPush(node)) { return; }else { try { backoff.backoff(); }catch(Exception e) { e.printStackTrace(); } } } } protected Node tryPop() throws EmptyException { int[] stamp = new int[1]; Node oldTop = top.get(stamp); if(oldTop == null) { throw new EmptyException(); } Node newTop = oldTop.next; if(top.compareAndSet(oldTop, newTop, stamp[0], stamp[0] + 1)) { return oldTop; }else { return null; } } public T pop() throws EmptyException { while(true) { Node returnNode = tryPop(); if(returnNode != null) { T value = returnNode.value; freeNode(returnNode); return value; }else { try { backoff.backoff(); }catch(Exception e) { e.printStackTrace(); } } } } } 
       
      
      
     
     
    
    
   
   

129.

1. 意义在于push和pop都是在top上的冲突,所以他们共享同一个backoff才能比较好的减少冲突。

2. 根据:add additional backoff delays before accessing the shared stack, and control whether to access the shared stack or the array dynamically。在policy中增加关于tryPush()和tryPop()成功和失败的计数。假设成功次数为s,失败次数为f,则成功率为 s / (s + f);则在tryPush()之前生成随机数r,如果 r % ((s + f) / s) == 0,则直接尝试tryPush(),否则直接从exchangers 入栈。

130.

将EliminationBackoffStack去掉tryPush和tryPop的部分,并将exchangers' capacity设为题目要求的界限。

131.

有类似于ABA的问题,比如:

1. top = 2, --> T1.pop() --> top = 1 --> T1.pop.i = 2, stack[2].value = value.T0

==> T2.pop() --> top = 0

==> T3.push() --> top = 1

==> T4.push() --> top = 2--> stack[2].value = value.T4; stack[2].full = true

==> T1.stack[2].full == true --> T1.pop() = value.T4

即T0写入的值被覆盖,丢失了。

2. top = 2 --> T1.pop --> top = 1 --> T1.i = 2

==> T2.push --> top = 2 --> T2.pushed

==> T3.pop --> top = 1, T3.i = 2

==> T3 && T1 pop the same item

问题在于push线程和pop线程之间没有同步,push线程并不知道当前操作的slot是否已经被pop了,即不能做到1对1。多个线程可能得到同一个index,因为取得index和读写操作并不原子,所以写/读的时候没有互斥;另外如果pop和push的速度太失衡,比如top.increase的速度总是赶不上pop.decrease的速度,会活锁。

package p131;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

import utils.EmptyException;
import utils.FullException;

public class DualStack
   
   
    
    
{
	public class Slot
	{
		public static final int EMPTY = 0;
		public static final int FULL = 1;
		public static final int BUSY = 2;

		volatile T value = null;
		AtomicStampedReference
    
    
     
      state = new AtomicStampedReference
     
     
      
      (EMPTY, 0);
	}
	
	Slot[] stack;
	int capacity;
	
	private AtomicInteger top = new AtomicInteger(0);
	
	@SuppressWarnings("unchecked")
	public DualStack(int myCapacity)
	{
		this.capacity = myCapacity;
		
		stack = new DualStack.Slot[capacity];
//		stack = (Slot[]) new Object[capacity];

		for(int i = 0; i < capacity; i ++)
		{
			stack[i] = new Slot();
		}
	}
	
	public void push(T value) throws FullException
	{
		while(true)
		{
			int i = top.getAndIncrement();
			if(i > capacity - 1)
			{
				top.compareAndSet(i, capacity);
				throw new FullException("" + i);
			}else if(i >= 0)
			{
				while(stack[i].state.getReference().intValue() != Slot.EMPTY) {}
				int[] stamp = new int[1];
				@SuppressWarnings("unused")
				int state = stack[i].state.get(stamp);
				if(!stack[i].state.compareAndSet(Slot.EMPTY, Slot.BUSY, stamp[0], stamp[0] + 1))
				{
					continue;
				}
				stack[i].value = value;
				stack[i].state.set(Slot.FULL, stamp[0] + 1);
//				System.out.println("stack " + i + " set full");
				return;
			}
		}
	}
	
	public T pop() throws EmptyException
	{
		while(true)
		{
			int i = top.getAndDecrement() - 1;
			if(i < 0)
			{
				top.compareAndSet(i + 1, 0);
				throw new EmptyException("" + (i + 1));
			}else if(i < capacity)
			{
//				System.out.println("Try to pop " + i);
				while(stack[i].state.getReference().intValue() != Slot.FULL) {}
				int[] stamp = new int[1];
				@SuppressWarnings("unused")
				int state = stack[i].state.get(stamp);
				T value = stack[i].value;
				if(!stack[i].state.compareAndSet(Slot.FULL, Slot.EMPTY, stamp[0], stamp[0]))
				{
					continue;
				}
				return value;
			}
		}
	}
	
	public int get()
	{
		return top.get();
	}
}

     
     
    
    
   
   

132.

1. 有131题类似的问题;还有越界的问题。比如:

T1.pop, top = -1 --> T2.pop, top = -2 --> T3.push, top = -1, items[-1] = x;

2. 如下所示。Rooms保证在所有的线程在由push和pop工作的转换中是静态一致的,所以保证操作的i都是有效的。同时如果2个push线程得到同一个index,他们之间必然已经隔了一段pop的执行;而在这个pop之前,第一个push线程必然已经完成items[i]=x的操作。如果这个slot没有被pop,则在第二次push阶段因为i = top.getAndIncrement()也不会被覆盖。

package p132;

import java.util.concurrent.atomic.AtomicInteger;

import p97.Rooms;
import utils.EmptyException;
import utils.FullException;

public class RoomsStack
   
   
    
    
{
	private AtomicInteger top;
	private T[] items;
	private Rooms rooms;
	public static final int PUSH = 0;
	public static final int POP = 1;
	
	@SuppressWarnings("unchecked")
	public RoomsStack(int capacity)
	{
		top = new AtomicInteger(0);
		items = (T[]) new Object[capacity];
		rooms = new Rooms(2);
	}
	
	public void push(T x) throws FullException
	{
		rooms.enter(PUSH);
		try
		{
			int i = top.getAndIncrement();
			if(i >= items.length)
			{
				top.getAndDecrement();
				throw new FullException();
			}
			items[i] = x;
		}finally
		{
			rooms.exit();
		}
	}
	
	public T pop() throws EmptyException
	{
		rooms.enter(POP);
		try
		{
			int i = top.getAndDecrement();
			if(i < 0)
			{
				top.getAndIncrement();
				throw new EmptyException();
			}
			return items[i];
		}finally
		{
			rooms.exit();
		}
	}
}

   
   

133.

	private class ExitHandler implements Rooms.Handler
	{
		public void onEmpty()
		{
			int newSize = items.length;
			@SuppressWarnings("unchecked")
			T[] newItems = (T[]) new Object[newSize];
			for(int i = 0 ; i < items.length; i ++)
			{
				newItems[i] = items[i];
			}
			items = newItems;
		}
	}
	
		@SuppressWarnings("unchecked")
	public RoomsStack(int capacity)
	{
		top = new AtomicInteger(0);
		items = (T[]) new Object[capacity];
		rooms = new Rooms(2);
		rooms.setExitHandler(PUSH, new ExitHandler());
	}
	
	public void push(T x)
	{
		while(true)
		{
			rooms.enter(PUSH);
			int i = top.getAndIncrement();
			if(i >= items.length)
			{
				top.getAndDecrement();
				rooms.exit();
			}else
			{
				items[i] = x;
				return;
			}
		}
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
1. 智慧监狱概述 智慧监狱的建设背景基于监狱信息化的发展历程,从最初的数字化监狱到信息化监狱,最终发展到智慧监狱。智慧监狱强调管理的精细化、监管的一体化、改造的科学化以及办公的无纸化。政策上,自2017年以来,司法部连续发布了多项指导性文件,推动智慧监狱的建设。 2. 内在需求与挑战 智慧监狱的内在需求包括数据应用与共享的不足、安防系统的单一功能、IT架构的复杂性、信息安全建设的薄弱以及IT运维的人工依赖。这些挑战要求监狱系统进行改革,以实现数据的深度利用和业务的智能化。 3. 技术架构与设计 智慧监狱的技术架构包括统一门户、信息安全、综合运维、安防集成平台和大数据平台。设计上,智慧监狱采用云计算、物联网、大数据和人工智能等技术,实现资源的动态分配、业务的快速部署和安全的主动防护。 4. 数据治理与应用 监狱数据应用现状面临数据分散和共享不足的问题。智慧监狱通过构建数据共享交换体系、数据治理工具及服务,以及基于数据仓库的数据分析模型,提升了数据的利用效率和决策支持能力。 5. 安全与运维 智慧监狱的信息安全建设涵盖了大数据应用、安全管理区、业务区等多个层面,确保了数据的安全和系统的稳定运行。同时,综合运维平台的建立,实现了IT系统的统一管理和自动化运维,提高了运维效率和系统的可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值