线程同部

synchronized关键字的作用域有二种:

1)是某个对象实例内,synchronized aMethod(){}

可以防止多个线程同时访问这个对象的synchronized方法

(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,

其它线程不能同时访问这个对象中任何一个synchronized方法)。

这时,不同的对象实例的synchronized方法是不相干扰的。

也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;
2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。

它可以对类的所有对象实例起作用。

除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中

表示只对这个区块的资源‘;实行互斥访问

用法是: synchronized(this){/*区块*/},它的作用域是当前对象

synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){}

而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法

synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。

如果再细的分类,synchronized可作用于instance变量、object reference(对象引用)、

static函数和class literals(类名称字面常量)身上。

明确几点:

A.无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象

  而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。

B.每个对象只有一个lock)与之相关联。

C.实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。

1、把synchronized当作函数修饰符时

public synchronized void test()
{...
}

这也就是同步方法,那这时synchronized锁定的是哪个对象呢?

它锁定的是调用这个同步方法对象。也就是说,当一个对象1在不同的线程中执行这个同步方法时

它们之间会形成互斥,达到同步的效果。

但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了synchronized关键字的方法。

等同于上述的代码:

public void test()
{synchronized (this)      {}
}

这里的this指的是调用这个对方法的对象

同部方法的实质是将synchronized作用于object reference

哪个拿到了对象1对象锁的线程,才可以调用对象1的同部方法

对于对象2来说,对象1这个锁与其毫不相干,程序也可能在这种情况下摆脱同部机制的控制

造成数据混乱

2、同部块

public void method3(SomeObject so){synchronized(so){//…..}
}

此时的锁就是so这个对象

谁拿到这个锁谁就可以运行它所控制的那段代码

当有一个明确的对象作为锁时,就写成这样的程序

但没有明确的对象作为锁,只是想让一段代码同部

可以创建一个特殊的instance变量来充当锁

class Foo implements Runnable
{private byte[] lock = new byte[0];  // 特殊的instance变量Public void methodA(){synchronized(lock) { //… }}
//…..
}

零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。

3、将synchronuzed作用于static函数

Class Foo{public synchronized static void methodAAA()   // 同步的static 函数{//….}public void methodBBB(){synchronized(Foo.class)   //  class literal(类名称字面常量)}
}

代码中的methodBBB()方法是把class literal作为锁的情况

它和同步的static函数产生的效果是一样的,取得的锁很特别

是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。

可以推断:如果一个类中定义了一个synchronized的static函数A

也定义了一个synchronized 的instance函数B

那么这个类的同一对象Obj在多线程中分别访问A和B两个方法时

不会构成同步,因为它们的锁都不一样。A方法的锁是Obj这个对象

而B的锁是Obj所属的那个Class。

总结:

1、线程同步的目的是为了保护多个线程反问一个资源时对资源的破坏。
2、线程同步方法是通过锁来实现,每个对象都有切仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其他访问该对象的线程就  无法再访问该对象的其他非同步方法
3、对于静态同步方法,锁是针对这个类的,锁对象是该类的Class对象。静态和非静态方法的锁互不干预。

  一个线程获得锁,当在一个同步方法中访问另外对象上的同步方法时,会获取这两个对象锁。
4、对于同步,要时刻清醒在哪个对象上同步,这是关键。
5、编写线程安全的类,需要时刻注意对多个线程竞争访问资源的逻辑和安全做出正确的判断,

  对“原子”操作做出分析,并保证原子操作期间别的线程  无法访问竞争资源。
6、当多个线程等待一个对象锁时,没有获取到锁的线程将发生阻塞。
7、死锁是线程间相互等待锁锁造成的,在实际中发生的概率非常的小。

  真让你写个死锁程序,不一定好使。但是,一旦程序发生死锁,程序将死掉。

实战小测试拿苹果的测试

苹果的数量是固定的,定义两个线程分别去去数据并进行打印

public class testTongBu implements Runnable{private int apple = 5;//拿苹果
    boolean getApple(){//将整个执行的代码锁起来//此每个线程只能单独的访问synchronized(this){if(apple > 0){System.out.println(Thread.currentThread().getName() +"拿走了一个apple");apple--;try {Thread.sleep(1500);} catch (InterruptedException e) {// TODO Auto-generated catch block
                e.printStackTrace();}System.out.println("还剩" + apple);return true;}return false;}}@Overridepublic void run() {boolean flag = getApple();while(flag){flag = getApple();}System.out.println("apple 没了");}public static void main(String[] args) {testTongBu t = new testTongBu();Thread t1 = new Thread(t);t1.setName("xiaoming");Thread t2 = new Thread(t);t2.setName("xiaoqiang");t1.start();t2.start();//多线程应用程序同时访问共享对象时,由于线程间相互抢占CPU的控制权,//造成一个线程夹在另一个线程的执行过程中运行,//所以可能导致错误的执行结果。
    }
}

转载于:https://www.cnblogs.com/Mrchengs/p/10803649.html

4、线程--线程同部相关推荐

  1. 【C++ 语言】线程 ( 线程创建方法 | 线程标识符 | 线程属性 | 线程属性初始化 | 线程属性销毁 | 分离线程 | 线程调度策略 | 线程优先级 | 线程等待 )

    文章目录 I 线程创建方法 II 线程执行函数 III 线程标识符 IV 线程属性 V 线程属性 1 ( 分离线程 | 非分离线程 ) VI 线程属性 2 ( 线程调度策略 ) VII 线程属性 3 ...

  2. 线程的创建 验证线程之间共享数据 守护线程 线程进程效率对比 锁 死锁 递归锁...

    线程(from threading import Thread):CPU调度的最小单位 线程的两种创建方式:方式一: 1 from threading import Thread 2 def f1(i ...

  3. java 线程一直运行状态_详解JAVA 线程-线程的状态有哪些?它是如何工作的?

    线程(Thread)是并发编程的基础,也是程序执行的最小单元,它依托进程而存在. 一个进程中可以包含多个线程,多线程可以共享一块内存空间和一组系统资源,因此线程之间的切换更加节省资源.更加轻量化,也因 ...

  4. 并发编程——线程——线程的理论和创建以及守护线程

    一.什么是线程 线程是操作系统能够进行运算调度的最小单位. 它被包含在进程之中,是进程中的实际运作单位. 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任 ...

  5. java线程——中断线程+线程状态+线程属性(优先级)

    [0]README 0.1) 本文描述转自 core java volume 1, 源代码为原创,旨在理解 java线程--中断线程+线程状态+线程属性(优先级) 的相关知识: [1]中断线程 1.1 ...

  6. linux 下的进程创建线程,Linux线程 之 线程 线程组 进程 轻量级进程(LWP)

    线程是有栈的,我们知道,普通的一个进程,它的栈空间是8M,我们可以通过ulmit -a查看: stack size (kbytes, -s) 8192 线程也不例外,线程也是需要栈空间的这句话是废话, ...

  7. 什么是线程线程和进程的区别

    什么是线程线程和进程的区别 线程是进程的一个实体,是cpu调度和分派的基本单位,比进程小可以独立运行的基本单位 一个进程包含多个线程具有独立功能的程序是操作系统进行资源分配和调度的一个独立单位

  8. 线程 - 线程安全 - 线程优化

    本文详尽的介绍了线程的相关知识,从概念到创建线程和其基本使用,又介绍了线程安全的相关知识,其中包含线程同步的四种实现方式与线程休眠的不同方式与其区别,最后介绍了线程优化包括线程优化.线程任务优化.锁优 ...

  9. Java坑人面试题系列: 线程/线程池(高级难度)

    ExecutorService 接口及相关API细节详解. Java Magazine上面有一个专门坑人的面试题系列: https://blogs.oracle.com/javamagazine/qu ...

  10. 集合到文件 文件到集合 点名器 集合到文件数据排序版 标准输入流 打印流 对象序列化流 对象返序列化流 Properties 游戏次数 进程和线程 线程 多线程的实现方式 设置和获取线程名称

    文章目录 集合到文件 文件到集合 点名器 集合到文件数据排序版 标准输入流 打印流 对象序列化流 对象返序列化流 Properties 游戏次数 进程和线程 线程 多线程的实现方式 设置和获取线程名称 ...

最新文章

  1. Android背景色渐变效果(shape,gradient) (转)
  2. python画图模块_学习python画图模块plotnine:第一步安装
  3. ann matlab,人工神经网络ann及其matlab仿真.ppt
  4. Linux 命令(127)—— wget 命令
  5. 【Luogu2142】【模板】高精度减法
  6. Python如何清屏命令行终端
  7. 张宇1000题高等数学 第九章 一元函数积分学的计算
  8. 打算开源一个低代码平台,第四天,包含【工作流,业务流,财务,APQC】。技术栈 React,typescript,java,mysql
  9. 网页和移动端使用一键添加qq群组件
  10. 吴22名广西农民工广东讨薪 返途被追砍(转载)
  11. auto.js B0012 进入各频道 查找父控件 子控件 2021-10-03
  12. 3种方式获取Wifi名称 兼容获取Wifi名字为空 WifiInfo.getSSID为空的情况
  13. 华为 GaussDB 数据库十问
  14. nexus2.5版本升级到nexus2.14(同时升级到nexus3.24版本)版本
  15. Mysql 内存管理及优化
  16. 穿过任意防火墙NAT的远程控制软件TeamViewer
  17. 国内外3D游戏开发流程和职位分类
  18. ae制作的mg如何用到html,【教程】AE表达式常用的函数-制作MG动画必备
  19. 嵌入式软件开发面试题总结四
  20. java计算机毕业设计共享顺风车管理系统MyBatis+系统+LW文档+源码+调试部署

热门文章

  1. .NET之EntityFramework框架运用
  2. 介绍PS大局观很不错的转文
  3. struts2配置中因为包名问题遇到的No result defined for action错误
  4. VC下关于debug和release的不同的讨论(收藏-转载)
  5. [19/05/06-星期一] JDBC(Java DataBase Connectivity,java数据库连接)_基本知识
  6. 一种简单的加解密算法
  7. 076 Apache的HBase与cdh的sqoop集成(不建议不同版本之间的集成)
  8. 截取 %# Eval(val) %中的字符
  9. C#远程连接Oracle数据库(不安装客户端)
  10. TimePickerDialog -下划线颜色修改