当前位置: 首页 > news >正文

线程不是独立的!而是同步的!

“你好,三妹子!我们有一种万能药,可以治愈所有疾病。正如我们所看到的,不受控制的线程切换是一个问题。”

“为什么线程本身不能决定何时切换到下一个线程?完成它们需要执行的所有工作然后发出信号“我完成了!”?

“允许线程自行控制切换将是一个更大的问题。假设你编写的代码不好,线程会永不放弃 CPU。在过去,这就是它的工作方式。那真是一场噩梦。”

“好的。那有什么解决方法呢?”

"阻塞其他线程。这就是它的工作方式。” 

显然,线程在尝试使用共享对象和/或资源时会互相干扰。就像在具有控制台输出的示例中所看到的那样:有一个控制台,所有线程都输出到该控制台。这太混乱了。

因此发明了一个特殊的对象:互斥锁。就像洗手间门上写着“无人/有人”的标志一样。它有两种状态:对象可用或被占用。这些状态也称为“锁定”和“解锁”。

当线程需要与其他线程共享的对象时,它将检查与该对象关联的互斥锁。如果互斥锁已解锁,则线程将锁定它(将其标记为“已占用”)并开始使用共享资源。线程完成业务后,互斥锁将被解锁(标记为“可用”)。

如果线程要使用该对象且互斥锁已锁定,则线程在等待时会进入休眠状态。当互斥锁最终被占用线程解锁时,我们的线程将立即锁定它并开始运行。洗手间门标志这个比喻非常恰当。

“如何使用互斥锁呢?我需要创建特殊对象吗?”

“比那简单多了。Java 的创建者将此互斥锁内置到 Object 类中。因此,你甚至不必创建它。它是每个对象的一部分。下面是它的工作原理:”

代码说明
class MyClass
{
private String name1 = "Ally";
private String name2 = "Lena";public void swap()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}
}
swap 方法交换 name1 和 name2 变量的值。

如果同时从两个线程中调用它会发生什么?

实际代码执行第一个线程的代码第二个线程的代码
String s1 = name1; //Ally
name1 = name2; //Lena
name2 = s1; //AllyString s2 = name1; //Lena
name1 = name2; //Ally
name2 = s2; //Lena
String s1 = name1; name1 = name2;
//other thread is running
name2 = s1;
//the thread waits until the mutex is unlockedString s2 = name1; name1 = name2;
//other thread is running
//other thread is running
name2 = s2;
末行
变量的值被交换两次,各自返回其原始位置。

注意关键字 synchronized

“嗯,它是什么意思?”

“当线程进入标记为 synchronized 的代码块时,Java 机器立即锁定 synchronized 一词后面括号内指示的对象的互斥锁。在我们的线程离开之前,没有其他线程可以进入此代码块。一旦我们的线程离开标记为 synchronized 的代码块,互斥锁将立即自动解锁,并可被另一个线程获取。”

如果互斥锁被占用,我们的线程将保持静止并等待其释放。

“如此简单精妙。很漂亮的解决方法。”

“是的。但是你知道在这种情况下会发生什么吗?”

代码说明
class MyClass
{
private String name1 = "Ally";
private String name2 = "Lena";public void swap()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}public void swap2()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}
}
swap 和 swap2 方法共享同一个互斥锁 (this) 对象。

如果一个线程调用 swap 方法,而另一个线程调用 swap2 方法会发生什么?

“由于互斥锁相同,因此第二个线程将不得不等待,直到第一个线程离开 synchronized 代码块为止。因此,同时访问不会有任何问题。”

“做得不错,阿米戈!这就是正确答案!”

现在我想指出的是,synchronized 不仅可以用于标记代码块,而且可以用于标记方法。如下所示:

代码实际发生的情况
class MyClass
{
private static String name1 = "Ally";
private static String name2 = "Lena";public synchronized void swap()
{
String s = name1;
name1 = name2;
name2 = s;
}public static synchronized void swap2()
{
String s = name1;
name1 = name2;
name2 = s;
}
}
class MyClass
{
private static String name1 = "Ally";
private static String name2 = "Lena";public void swap()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}public static void swap2()
{
synchronized (MyClass.class)
{
String s = name1;
name1 = name2;
name2 = s;
}
}
http://www.dtcms.com/a/598625.html

相关文章:

  • 招商加盟网站推广方案济南做网站要多少钱
  • 做网站apache如何网站建设找超速云建站
  • 网站关联页面如何做大连网龙网络科技
  • 网站推广策划的思路包括哪些内容中国黄页
  • LeetCode hot100:234 回文链表:快慢指针巧判回文链表
  • 合肥网站建设方案服务营销网站搭建建议
  • 【python】生成器
  • 昆明展示型网站开发网站添加百度地图导航
  • 网站地图什么时候提交好广州网站建设推广方法
  • python的网站开发免费软件库下载
  • 阿里云服务器创建网站吗动漫制作专业用什么笔记本电脑
  • 若依 springBoot 配置国际化
  • 十年经验网站开发公司安阳市商祺网络有限责任公司
  • 网络初识~
  • 织梦怎么做中英文网站做网站只做前端可以用吗
  • C 语言17:位操作符 | ^:从二进制编码到大小端
  • 计算机网站php设计代做平台公司和项目公司的区别
  • flowable04网关和变量
  • 设计旅游网站的主色调sem工具是什么
  • 如何降低交互复杂度,减少用户学习成本
  • 交易类网站做支付宝功能淘宝网站代理怎么做
  • 中国建设银行网站如何注册logo设计公司 南京
  • 麒麟桌面操作系统切换到root用户方法
  • 找企业名录的网站网站的横幅怎么做
  • 工具学习_Vulrule
  • 上海外贸soho网站建设静态网站登陆怎么做
  • 哈希表中桶的概念
  • 网站建设系统设计重庆百度搜索排名优化
  • 中山快速做网站服务盐城网站建设流程
  • LangFlow 中,节点间的数据流动核心是 **“输入-输出端口映射”+“执行链路驱动”**