多线程编程-- part 3 多线程同步->synchronized关键字
多线程同时访问一个资源,可以会产生不可预料的结果,所以为这个资源加锁,访问资源的第一个线程为其加锁后,其他线程便不能在使用那个资源,直到锁被解除。
举个例子:
存款1000元,能取出800的时候我就取800,当我同时用两个线程调用这个取钱操作时,有时可以取出1600元
static class HelloRunable implements Runnable{
private int money = 1000;
//取出800元
int getMoney() {
System.out.println("开始" + money);
if(money > 800) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
money -= 800;
System.out.println("我取了800元" + money);
}
System.out.println("结束" + money);
return money;
}
@Override
public void run() {
money = getMoney();
}
}
public static void main(String[] args) {
HelloRunable helloRunable = new HelloRunable();
Thread t = new Thread(helloRunable);
Thread t1 = new Thread(helloRunable);
t.start();
t1.start();
}

synchronized:
所以我们引入了同步机制,在取钱方法前面加入了synchronized关键字,该方法称为同步方法,输出结果为

java中每个对象都有一个锁,或者叫做监视器(monitor),当一个线程访问某个对象的synchronized方法时,将该对象上锁,其他任何线程都无法再去访问该对象的synchronized方法,直到之前的那个线程执行完方法之后,才会将对象锁释放,其他线程才可以在用该对象的synchronized方法。 注:这是给对象上锁,如果是不同的对象则该对象之间没有限制关系。
如果一个对象有多个synchronized方法,某一时刻某个线程已经进入到了synchronized方法,那么在该方法没有执行完前,其他线程是无法访问该对象的任何synchronized方法的。
例如:
public static void main(String[] args)
{
Example example = new Example(); Thread t1 = new Thread1(example);
Thread t2 = new Thread2(example); t1.start();
t2.start();
} static class Example
{
public synchronized void execute()
{
for (int i = 0; i < 20; ++i)
{
try
{
Thread.sleep((long) Math.random() * 1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("Hello: " + i);
}
} public void execute2()
{
for (int i = 0; i < 20; ++i)
{
try
{
Thread.sleep((long) Math.random() * 1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("World: " + i);
}
} } static class Thread1 extends Thread
{
private Example example; public Thread1(Example example)
{
this.example = example;
} @Override
public void run()
{
example.execute();
} } static class Thread2 extends Thread
{
private Example example; public Thread2(Example example)
{
this.example = example;
} @Override
public void run()
{
example.execute2();
} }

当加上synchronized后,当同步方法未执行完时另一个同步方法不会执行

静态的同步方法
当一个synchronized关键字修饰的方法同时被static修饰,非静态的同步方法会将对象上锁,但是静态方法不属于对象,而是属于类,他会将这个方法所在的类的Class对象上锁。
public static void main(String[] args)
{
Example example = new Example(); Thread t1 = new Thread1(example); example = new Example();
Thread t2 = new Thread2(example); t1.start();
t2.start();
} static class Example
{
public static synchronized void execute()
{
for (int i = 0; i < 20; ++i)
{
try
{
Thread.sleep((long) Math.random() * 1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("Hello: " + i);
}
} public static synchronized void execute2()
{
for (int i = 0; i < 20; ++i)
{
try
{
Thread.sleep((long) Math.random() * 1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("World: " + i);
}
} } static class Thread1 extends Thread
{
private Example example; public Thread1(Example example)
{
this.example = example;
} @Override
public void run()
{
example.execute();
} } static class Thread2 extends Thread
{
private Example example; public Thread2(Example example)
{
this.example = example;
} @Override
public void run()
{
example.execute2();
} }

不加静态方法方法:

当某个synchronized方法是static的,那么当线程访问该方法时,他锁的并不是synchronized方法所在的对象,而是synchronized方法所在类的对应的class对象(java中,一个类无论有多少对象,这些对象会对应唯一的class对象,因此当线程分别访问一个类的两个对象的的两个static synchronized方法时,他们的执行顺序也是有顺序的,也就是说一个线程先去执行,执行完释放锁,另一个线程再去执行)
synchronized代码块
synchronized(object) {
}
表示的是在执行过程中会将object对象上锁(这个对象可以使任意类的对象,也可以使用this),可以自行规定上锁对象
public class test {
public static void main(String[] args) {
Example example = new Example();
Thread t1 = new Thread1(example);
Thread t2 = new Thread2(example);
t1.start();
t2.start();
}
}
class Example {
private Object object = new Object();
public void execute() {
System.out.println("我开始了");
synchronized (object) {
for (int i = 0; i < 20; ++i) {
try {
Thread.sleep((long) Math.random() * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Hello: " + i);
}
}
}
public void execute2() {
System.out.println("我也开始了");
synchronized (object) {
for (int i = 0; i < 20; ++i) {
try {
Thread.sleep((long) Math.random() * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("World: " + i);
}
}
}
}
class Thread1 extends Thread {
private Example example;
public Thread1(Example example) {
this.example = example;
}
@Override
public void run() {
example.execute();
}
}
class Thread2 extends Thread {
private Example example;
public Thread2(Example example) {
this.example = example;
}
@Override
public void run() {
example.execute2();
}
}

可以看到除了synchronized代码块里的方法,其他是不会同步执行的。
synchronized方法是一种粗粒度的并发控制,某一时刻,只能有一个线程执行synchronized方法。
synchronized块则是细粒度的并发控制,只会将块中的代码同步,方法内的其他代码是可以被多个线程同时访问到的
多线程编程-- part 3 多线程同步->synchronized关键字的更多相关文章
- “全栈2019”Java多线程第十六章:同步synchronized关键字详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Java多线程同步 synchronized 关键字的使用
代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D)运行完这个方法后再运行此线程A, ...
- 多线程学习-基础( 九)线程同步Synchronized关键字
一.线程同步1.synchronized关键字的作用域有二种:(1)某个对象实例内:synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果 ...
- java 多线程:Thread 并发线程: 方法同步synchronized关键字,与static的结合
1.方法内的变量是安全的 方法内定义的变量,每个变量对应单独的内存变量地址,多个线程之间相互不影响.多个线程之间的变量根本没有一毛钱关系 public class ThreadFuncVarSafe ...
- Java多线程系列--“基础篇”04之 synchronized关键字
概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ...
- 2.3多线程(java学习笔记)synchronized关键字
一.为什么要用synchronized关键字 首先多线程中多个线程运行面临共享数据同步的问题. 多线程正常使用共享数据时需要经过以下步骤: 1.线程A从共享数据区中复制出数据副本,然后处理. 2.线程 ...
- Java多线程编程核心技术---Java多线程技能
基本概念 进程是操作系统结构的基础,是一次程序的执行,是一个程序及其数据结构在处理机上顺序执行时所发生的活动,是程序在一个数据集合上运行的过程,是系统进行资源分配和调度的独立单位.线程可以理解成是在进 ...
- Java多线程编程核心技术(三)多线程通信
线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时 ...
- (1)Java多线程编程核心——Java多线程技能
1.为什么要使用多线程?多线程的优点? 提高CPU的利用率 2.什么是多线程? 3.Java实现多线程编程的两种方式? a.继承Thread类 public class MyThread01 exte ...
随机推荐
- Windows入门基础:1.关于CreateWindow()函数使用中遇到的问题
我在实现显示窗口的程序中,遇到一个问题:首先程序没有任何语法错误,编译能够通过,但是就是不能弹出窗口. 后来在MSDN中查询CreateWindow()函数,发现了下面这句话: "If lp ...
- 告别S! S! H!秒杀终端工具——FastLogin快捷登录
题记:自从接触到"跳板机"的概念后,一直就被烦不胜烦的机器名,ip地址,用户名,密码折腾的死去活来,心说能有个小精灵随时帮我输入那些重复的登录信息就好了.我见过最挫的方式就是用记事 ...
- 【R.转载】apply函数族的使用方法
为什么用apply 因为我是一个程序员,所以在最初学习R的时候,当成"又一门编程语言"来学习,但是怎么学都觉得别扭.现在我的看法倾向于,R不是一种通用型的编程语言,而是一种统计领域 ...
- 基于Prism.Windows的UWP开发备忘
以前做UWP开发都是使用MvvmLight,主要是简单易上手,同时也写了很多MvvmLight的开发系列文章: UWP开发必备以及常用知识点总结 UWP开发之Mvvmlight实践九:基于MVVM的项 ...
- inform表单验证,正则表达式,用户名,身份证,密码,验证码
最近利用空闲时间写了部分表单验证,包括用户名,身份证,密码,验证码,仅为自己巩固最近所学的知识 表单的样式使用的是table布局,因为觉得DIV布局定位比较麻烦,table有三列,分别为基本信息,输入 ...
- JavaWeb的国际化(17/4/8)
国际化的缺点: 因为文字不同,所以带来的排版问题一样严重,通常都是重新在写一个网站反而更加清晰,快捷 1:需要从浏览器中获取到浏览器语言(Accept-Language) 2:利用locale获取 ...
- 事件的preventDefault方法
事件有一个preventDefault()方法,该方法可以用来取消事件的默认行为.许多事件都有默认执行的关联行为.例如,如果用户在文本字段中键入一个字符,则默认行为就是在文本字段中显示该字符.由于可以 ...
- Linux 系统管理06--磁盘管理
Linux系统管理06——磁盘管理 一.磁盘结构 1.硬盘的物理结构 盘片:硬盘有多个盘片,每个盘片2面 磁头:每面一个磁头 2.硬盘的数据结构 扇区:盘片被分为多个扇形区域,每个扇形区存放512字节 ...
- python在接口测试的实际应用
今天看到@51Testing软件测试网 关于"关于接口测试的总结"的文章,进去浏览了一下,文章主要是针对接口测试的理论性的描述,而实战的内容没有涉及到.刚好今天我将我的系列文章的& ...
- CSS3 基础知识[转载minsong的博客]
CSS3 基础知识1.边框 1.1 圆角 border-radius:5px 0 0 5px; 1.2 阴影 box-shadow:2px 3px 4px 5px rgba(0,0,0 ...