一个原子操作,保证一个线程在一瞬间完全执行
没有其他线程可见的中间状态
不是很明显什么操作是原子的,比如x++不是原子的,因为它可能变成多个机器指令
LOAD R,x
INC R
STORE R,x
每个线程都有自己的执行堆栈,所以使用相同寄存器变量R的两个线程没有问题(它们在交换线程时被保存/恢复)
如果线程通过非原子操作进行交换,可能会发生“奇怪的事情”(竞态条件)
如果一个线程试图读取一个全局变量/字段,而另一个线程正在更改它的值,读取的值取决于线程交换执行时的精确时间
场景1:线程A开始执行x++,但线程B在线程A存储新值之前读取了x(线程B获得了原始值)
LOAD R,x
INC R
LOAD R,x
STORE R,x
场景2:线程A执行x++,然后线程B随后读取x(线程B获得增量值)
LOAD R,x
INC R
STORE R,x
LOAD R,x
当两个线程修改相同的共享状态时,也会发生更糟糕的“奇怪的事情”
示例:线程A执行x++,而线程B也执行x++
场景1:线程A执行x++然后线程B执行x++ (x加2)
LOAD R,x
INC R
STORE R,x
LOAD R,x
INC R
STORE R,x
场景2:线程A开始执行x++,但是线程B在线程A存储新值之前读取了x (x只加1)
LOAD R,x
INC R
LOAD R,x
INC R
STORE R,x
STORE R,x
被称为“更新丟失问题”
即使多个线程执行代码来更新共享状态,有时只出现一些更新
调试可能非常具有挑战性
示例代码LostUpdate
/**
A class that demonstrates the lost update problem in concurrency
by creating two threads that concurrently try to increment x
each a total of ITERATIONS times.
Sometimes the final value of x is not 2*ITERATIONS
*/
public class LostUpdate implements Runnable
{
private int x;
private static final int ITERATIONS = 20000000; // multiple of 10
public LostUpdate()
{
x = 0;
}
// repeatedly increment the value of x
public void run()
{
System.out.println("Thread " + Thread.currentThread()
+ " started with x = " + x);
int loopIterations = ITERATIONS/10;
for (int i=0; i<loopIterations; i++)
{
x++; x++; x++; x++; x++; x++; x++; x++; x++; x++;
}
System.out.println("Thread " + Thread.currentThread()
+ " finishing with x = " + x);
}
public static void main(String[] args)
{
// create two concurrent threads
LostUpdate lostUpdate = new LostUpdate();
Thread threadA = new Thread(lostUpdate);
Thread threadB = new Thread(lostUpdate);
threadA.start();
threadB.start();
try
{
// wait for both threads to finish
threadA.join();
threadB.join();
}
catch (InterruptedException e)
{
System.out.println("Interrupted " + e);
}
System.out.println("The final value of x is " + lostUpdate.x);
}
}
***互斥算法***是一种实现互斥的算法
如何不写互斥算法(因为它并不总是保证互斥对于线程t,使用一个名为***exclude***的布尔标志
**Incorrect-Acquire-Lock(t)**
1 while exclude do
2 delay
3 exclude <- true
**Incorrect-Release-Lock(t)**
1 exclude <- false
简单地使用布尔标志可能无法进行测试,并且设置标志可能不是原子的
Dekker 's Algorithm是第一个正确处理(仅)两个线程的互斥的算法:
为每个线程维护一个请求标志,当线程请求锁时设置该标志
维护一个优先级变量,以指示在平局情况下,两个线程中接下来应该访问哪个线程
**Dekker-Acquire-Lock(t)**
1 s <- the other thread than t
2 requested[t] <- true
3 while requested[s] do
4 if priority = s then
5 requested[t] <- false
6 while priority = s do
7 delay
8 requested[t] <- true
**Dekker-Release-Lock(t)**
1 s <- the other thread than t
2 priority <- s 3 requested[t] <- false
Peterson算法简化了Dekker算法
在变量回合中利用竞争条件
**Peterson-Acquire-Lock(t)**
1 s <- the other thread than
2 requested[t] <- true
3 turn <- t 4 while turn = t and requested[s] do
5 delay
**Peterson-Release-Lock(t)**
1 requested[t] <- false
可以修改为也工作在两个以上的线程(过滤算法)
Lamport的bakery算法可以处理任意数量的线程
Lamport-Acquire-Lock(t)
1 choosing[t] <- true
2 assign a number to thread t one larger than currently assigned maximum
3 choosing[t] <- false
4 for each thread s do
5 while choosing[s] do
6 delay
7 while (num[s]≠0 and num[s]<num[t]) or
(num[s]=num[t] and Id[s]<Id[t]) do
8 delay
Lamport-Release-Lock(t)
1 num[t] <- 0
许多进程支持测试和设置指令
原子测试和设置操作有助于创建简单的互斥锁算法
TestAndSet-Acquire-Lock(t)
1 while TestAndSet(exclude, true) do
2 delay
TestAndSet-Release-Lock(t)
1 TestAndSet(exclude, false)
互斥:https://en.wikipedia.org/wiki/Mutual_exclusion
Leslie Lamport的面包店算法论文:http://lamport.azurewebsites.net/pubs/bakery.pdf
Multiply(Intro)Write a function that will receive 2 numbers as input and it should return the multiplication of these 2 numbers.Input: Two arguments. Both are of type int.Output: Int.Example:mult_two(2, 3) == 6mult_two(1, 0) == 0code:def mult_two(
抽取JDBC工具类 : JDBCUtils目的:简化书写分析:注册驱动也抽取抽取一个方法获取连接对象需求:不想传递参数(麻烦),还得保证工具类的通用性。解决:配置文件jdbc.propertiesurl=user=password=抽取一个方法释放资源抽取注册驱动,抽取一个方法释放资源/** * JDBC工具类 */public class JDBCUtils { private static String url; privat
接上一篇,使用 Intent 从 MainActivity 跳转到 FirstActivity ,不需要 FirstActivity 回传数据就用 startActivity,val intent = Intent(this, FirstActivity::class.java)intent.putExtra("key_from_main", "data_from_main")startActivity(intent)需要 FirstActivity 回传数据就用 startActivityF
物质自旋与力的形成——关于万有引力与磁荷力本质与统一问题的探讨司 今(广州毅昌科技研究院 广州 510663 E-mail:[email protected])一、引言万有引力三百多年前,牛顿发现万有引力定律,即F=GMm/R²,这个公式首次揭示了一个场力与距离平方成反比的时代;一百多年后,库伦受万有引力定律和电荷概念的启迪,又分别发现了电荷、磁荷的场力定律,即F=ke q1 q2 /r²、F=...
L2-017. 人以群分 时间限制 150 ms内存限制 65536 kB代码长度限制 8000 B判题程序 Standard 作者 陈越社交网络中我们给每个人定义了一个“活跃度”,现希望根据这个指标把人群分为两大类,即外向型(outgoing,即活跃度高的)和内向型(introverted,即活跃度低的)。要求两类人群的规模尽可能接近,而他们...
L2-017. 人以群分时间限制150 ms内存限制65536 kB代码长度限制8000 B判题程序Standard作者陈越社交网络中我们给每个人定义了一个“活跃度”,现希望根据这个指标把人群分为两大类,即外向型(outgoing,即活跃度高的)和内向
GIS相关源归纳整理1.GIS算法库2.GIS资料整理开源GIS图形引擎或小型GIS可视化库GIS数据解析三维地形服务GIS数据展示工具GIS数据处理矢量瓦片生成处理相关GIS数据其他3.其他内容1.GIS算法库Liang-Barsky线裁剪算法寻路算法流线算法几何数据处理(联合、相交等)3D几何网格数据压缩与解压自动拟合数字化曲线算法2D矩形空间索引的快速建立地理坐标库,支持坐标系的相互转换(WGS84,GCJ02,BD09等),支持GeoJSONproj4js地理坐标转换库基于K
社交网络中我们给每个人定义了一个“活跃度”,现希望根据这个指标把人群分为两大类,即外向型(outgoing,即活跃度高的)和内向型(introverted,即活跃度低的)。要求两类人群的规模尽可能接近,而他们的总活跃度差距尽可能拉开。输入格式:输入第一行给出一个正整数N(2 &lt;= N &lt;=10^5^)。随后一行给出N个正整数,分别是每个人的活跃度,其间以空格分隔。题目保证这些数字以及它...
一. 简介Airflow 是一个使用 Python 语言编写的 Data Pipeline 调度和监控工作流的平台。分布式任务调度框架Airflow 是通过 DAG(Directed acyclic graph 有向无环图)来管理任务流程的任务调度工具,不需要知道业务数据的具体内容,设置任务的依赖关系即可实现任务调度。这个平台拥有和 Hive、Presto、MySQL、HDFS、Postgres 等数据源之间交互的能力,并且提供了钩子(hook)使其拥有很好地扩展性。除了使用命令行,该工具还提供了一
本地缓存传值 localStorage/sessionStorage。router路由传参query/params。注入的方式传值 provide/inject。消息订阅与发表pubsub-js。路由组件方式传值[:xxx]vuex状态管理工具传值。
JSLT标签库,是日常开发经常使用的,也是众多标签中性能最好的。把常用的内容,放在这里备份一份,随用随查。尽量做到不用查,就可以随手就可以写出来。这算是Java程序员的基本功吧,一定要扎实。 JSTL全名为JavaServer Pages Standard Tag Library,目前最新的版本为1.1版。JSTL是由JCP(Java Community Process)所制定的标准规范,
导读import cv2import numpy as npdef remove_red_seal(input_img): # 通道分离 blue_c, green_c, red_c = cv2.split(input_img) # 选择阈值 thresh, ret = cv2.threshold(red_c, 0, 255,cv2.THRESH_TRIANGLE) # filter_condition = int(thresh * 0.9) fil