java同步synchronized
volatile仅仅用来保证该变量对所有线程的可见性,但不保证原子性。
看下面的这段代码:
- /**
- *
- * @author InJavaWeTrust
- *
- */
- public class CountVolatile implements Runnable {
- public static CountVolatile instance = new CountVolatile();
- public static volatile int i = 0;
- public static void increate() {
- i++;
- }
- public void run() {
- for (int c = 0; c < 10000000; c++) {
- increate();
- }
- }
- public static void main(String[] args) throws InterruptedException {
- Thread t1 = new Thread(instance);
- Thread t2 = new Thread(instance);
- t1.start();
- t2.start();
- t1.join();
- t2.join();
- System.out.println(i);
- }
- }
这段代码演示了一个计数器,两个线程同时对i进行累加,个执行10000000次。我们希望的执行结果是最终i的值可以达到20000000,但事实并非总是如此。很多时候,i的值会小于期望的数值20000000。这是因为两个线程同时对i进行写入时,其中一个线程的结果会覆盖另外一个线程的结果。
要从根本上解决这个问题,我们就必须保证多个线程在对i进行操作时完全同步。
关键字synchronized的作用是实现线程间的同步。当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
关键字synchronized的几种用法。
- 指定加锁对象:对给定对象加锁,进入同步代码钱要获得给定对象的锁。
- 直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。
- 直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。
一、指定加锁对象:
- /**
- *
- * @author InJavaWeTrust
- *
- */
- public class CountSynchronized implements Runnable {
- public static CountSynchronized instance = new CountSynchronized();
- public static int i = 0;
- public void run() {
- for (int c = 0; c < 10000000; c++) {
- synchronized(instance) { //对给定对象加锁
- i++;
- }
- }
- }
- public static void main(String[] args) throws InterruptedException {
- Thread t1 = new Thread(instance);
- Thread t2 = new Thread(instance);
- t1.start();
- t2.start();
- t1.join();
- t2.join();
- System.out.println(i);
- }
- }
二、直接作用于实例方法:
- /**
- *
- * @author InJavaWeTrust
- *
- */
- public class CountSynchronized2 implements Runnable {
- public static CountSynchronized2 instance = new CountSynchronized2();
- public static int i = 0;
- public synchronized void increate() { //对当前实例方法加锁
- i++;
- }
- public void run() {
- for (int c = 0; c < 10000000; c++) {
- increate();
- }
- }
- public static void main(String[] args) throws InterruptedException {
- Thread t1 = new Thread(instance);
- Thread t2 = new Thread(instance);
- t1.start();
- t2.start();
- t1.join();
- t2.join();
- System.out.println(i);
- }
- }
三、直接作用于静态方法:
- /**
- *
- * @author InJavaWeTrust
- *
- */
- public class CountStaticMethod implements Runnable {
- static int i = 0;
- public static synchronized void increate() { //相当于对当前类加锁
- i++;
- }
- public void run() {
- for (int c = 0; c < 10000000; c++) {
- increate();
- }
- }
- public static void main(String[] args) throws InterruptedException {
- Thread t1 = new Thread(new CountStaticMethod());//new一个对象
- Thread t2 = new Thread(new CountStaticMethod());//new一个对象
- t1.start();
- t2.start();
- t1.join();
- t2.join();
- System.out.println(i);
- }
- }
java同步synchronized的更多相关文章
- 转:Java同步synchronized使用
原文链接 作者:Jakob Jenkov Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java同步块用来避免竞争.本文介绍以下内容: Java同步关键字(s ...
- Java同步synchronized与死锁
多个线程要操作同一资源时就有可能出现资源的同步问题. 同步就是指多个操作在同一个时间段内只能有一个线程进行,其他线程要等待此线程完成之后才可以继续执行. 解决资源共享的同步操作,可以使用同步代码块和同 ...
- java 同步 synchronized
http://www.cnblogs.com/Qian123/p/5691705.html http://www.cnblogs.com/GnagWang/archive/2011/02/27/196 ...
- Java多线程同步 synchronized 关键字的使用
代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D)运行完这个方法后再运行此线程A, ...
- Java的synchronized关键字:同步机制总结
JAVA中synchronized关键字能够作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块.搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程 ...
- Java同步块(synchronized block)使用详解
Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java同步块用来避免竞争.本文介绍以下内容: Java同步关键字(synchronzied) 实例方法同步 静 ...
- 015-线程同步-synchronized几种加锁方式、Java对象头和Monitor、Mutex Lock、JDK1.6对synchronized锁的优化实现
一.synchronized概述基本使用 为确保共享变量不会出现并发问题,通常会对修改共享变量的代码块用synchronized加锁,确保同一时刻只有一个线程在修改共享变量,从而避免并发问题. syn ...
- “全栈2019”Java多线程第十六章:同步synchronized关键字详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Java同步机制总结--synchronized
不久前用到了同步,现在回过头来对JAVA中的同步做个总结,以对前段时间工作的总结和自我技术的条理话.JAVA中synchronized关键字能够 作为函数的修饰符,也可作为函数内的语句,也就是平时说的 ...
随机推荐
- ref string
string pics=""; pSub.GetSubjectContent(pddm,ref pics); public string GetSubjectContent(st ...
- 使用webpack-dev-server设置反向代理解决前端跨域问题
webpack-dev-server是一个小型的Node.js Express服务器,它使用webpack-dev-middleware来服务于webpack的包,除此自外,它还有一个通过Sock.j ...
- 游戏流程&游戏规则
- Linux下查看alert日志文件的两种方法
--linux下查看alert日志文件的两种方法: --方法1: SQL> show parameter background_dump_dest; NAME TYPE VALUE ------ ...
- Linux shell爬虫实现树洞网自动回复Robot
奇怪的赞数 人生在世,不如意事十之八九,可与言者无二三人.幸好我们生在互联网时代,现实中找不到可以倾诉的人还可以在网络上寻找发情绪宣泄口,树洞这类产品就是提供一个让人在网络上匿名倾诉的平台. 我是偶然 ...
- Singular value decomposition
SVD is a factorization of a real or complex matrix. It has many useful applications in signal proces ...
- pg备份恢复与设置编码
psql create database jasygl encoding='UTF8' TEMPLATE = template0; 命令行 备份 pg_dump dabase_name > ba ...
- Compass实战 站内搜索
今天早上打算对这两天学习的Lucene以及Compass总结一下,想来想去,还是写个小项目来验证最好了.于是就有了今天的这篇文章.难易程度适合对于Compass或者Lucene刚入门的童鞋,大牛看到后 ...
- ejabberd mod_echo 解析
ejabberd mod_echo 解析(金庆的专栏 2016.8)按开发入门的说明,mod_echo是最简单的模块之一.https://docs.ejabberd.im/developer/当然 m ...
- 软件测试之BUG分析定位概述(QA如何分析定位BUG)
你是否遇到这样的场景? QA发现问题后找到DEV说: 不好了,你的程序出问题了! DEV(追查半小时之后): 唉,是你们测试环境配置的问题 唉,是你们数据不一致 唉,是你们**程序版本不对 唉,是** ...