活性(Liveness)

并发应用程序及时执行的能力被叫做它的活性。这块描述了最普通的活性问题,死锁(deadlock),接着简单描述了两个其他活性问题“饥饿锁和活锁”;

死锁

死锁描述了一种情形,两个或者更多的线程徐翔阻塞。,互相等待对方。这里是一个例子。

Alphonse和Gaston是好朋友,非常看重礼节。礼节的一个严格规定是当你向一个朋友鞠躬的时候,你必须保持鞠躬状态知道你的朋友向你鞠躬。不幸的是,这中规定没有考虑到这种可能性两个朋友同时向对方鞠躬。这个应用例子,死锁,模拟了这种可能。

public class Deadlock {
static class Friend {
private final String name;
public Friend(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public synchronized void bow(Friend bower) {
System.out.format("%s: %s"
+ " has bowed to me!%n",
this.name, bower.getName());
bower.bowBack(this);
}
public synchronized void bowBack(Friend bower) {
System.out.format("%s: %s"
+ " has bowed back to me!%n",
this.name, bower.getName());
}
}

public static void main(String[] args) {
final Friend alphonse =
new Friend("Alphonse");
final Friend gaston =
new Friend("Gaston");
new Thread(new Runnable() {
public void run() { alphonse.bow(gaston); }
}).start();
new Thread(new Runnable() {
public void run() { gaston.bow(alphonse); }
}).start();
}
}


当死锁运行的时候,它极像两个线程努力调用bowBack时将互相阻塞。阻塞将永远不会结束,因为双方都在等待另一个退出bow。

饥饿和活锁

饥饿和活锁问题比死锁不常见。但是仍然是每个并发应用设计者可能遇到的问题。

饥饿

饥饿描述了这样的一种情形,饥饿描述的是一个线程不能定期的获取对共享资源的访问并且不能前进。当共享资源由于贪婪的线程长期占用而变得不可用就发生了。例如,假设一个对象提供了一个同步方法需要花费很长时间返回。如果一个线程频繁的调用这种方法,其他也需要频繁同步访问这个相同对象的线程就会被阻塞。

活锁(LiveLock)

A线程要以C线程执行后的响应才执行。如果B线程也是以C线程动作的响应才能执行。活锁就可能发生。和死锁一样,活锁的线程不能继续下一步动作。可是了,这些线程没有阻塞,它们只是忙于响应每个线程来重新工作。这就好比两个人在走廊中互相穿过对方:Alphonse 移动到他的左边让Gaston 过,而Gaston 移动到他的右边让Alphonse 过。看见他们仍然互相阻塞对方。Alphonse 移动到他的右边,而Gaston 移动到他的左边,他们仍旧阻塞对方,这样。。。。。
### Petri网的活性概念及其判断方法 #### 活性Liveness)的概念 Petri网中的活性是指系统能够始终保持其动态行为的能力。具体来说,如果在一个Petri网中,所有的变迁在某些条件下都可以被激发,则该Petri网被认为是活的。根据不同的条件约束,活性分为多个等级: - **0-活性**:至少存在一条变迁可以在某种情况下被激发[^1]。 - **1-活性**:对于每一个变迁 \( t \),都存在一种标记使得 \( t \) 可以被激发[^2]。 - **k-活性 (k ≥ 2)**:不仅每个变迁都能被激发,而且在网络经历任意有限次激发序列之后,仍然能回到允许所有变迁再次激发的状态。 #### 判断Petri网是否具有活性的方法 为了验证一个给定的Petri网是否满足特定级别的活性,通常采用以下几种方法和技术: 1. **可达图分析** 构造Petri网的可达图是一种直接但可能计算复杂度较高的方式来评估活性。通过遍历所有可能达到的状态(即不同令牌配置下的标记),检查是否存在任何状态下有无法触发的变迁。这种方法理论上适用于小型或中型规模的Petri网,但对于大型复杂的网络可能会遇到状态爆炸问题[^3]。 2. **不变量分析** 使用地方不变量和过渡不变量可以帮助简化活性检测过程。这些不变量提供了关于系统的结构性质的信息,在不需要完全展开整个状态空间的情况下推导出有关活性的结果[^4]。 3. **线性代数方法** 将Petri网转换成矩阵形式并通过求解相应的方程组来进行分析也是一种常见手段。例如,利用关联矩阵\( C=[c_{ij}] \)(其中\( c_{ij} \) 表示第i个库所到第j个变迁之间的权值关系) 和初始标记向量M₀, 结合转移函数F(M), 来判定是否存在循环路径覆盖全部节点从而保证整体活性[^5]。 ```python import numpy as np def is_living_petri_net(C_matrix, M_initial): """ A simple function to check liveness using linear algebra approach. Parameters: C_matrix : ndarray Incidence matrix of the Petri net. M_initial : list or array-like Initial marking vector. Returns: bool indicating whether the given Petri net configuration has potential for full activity under certain conditions. """ # Convert inputs into NumPy arrays if not already done so C = np.array(C_matrix) m_init = np.array(M_initial) # Define a transition firing rule based on incidence structure... def can_fire(t_index, current_marking): return all(current_marking >= row[t_index] * (-row.sum()) for row in C.T) possible_transitions = set(range(len(C))) active_set = {t for t in possible_transitions if can_fire(t, m_init)} while True: new_activations = False temp_active = active_set.copy() for t in possible_transitions.difference(temp_active): updated_m = m_init + sum([C[:,a]*(-sum(C[a,:])) for a in temp_active]) if can_fire(t,updated_m): active_set.add(t) new_activations = True if not new_activations: break return len(active_set)==len(possible_transitions) ``` 此代码片段展示了一个基于Python实现的基础框架用于探索简单的Petri网模型是否有潜力维持全活动状态。注意这只是一个非常初步的例子,并未考虑实际应用中的诸多细节优化以及边界情况处理等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值