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);
}
}

最新文章

  1. Dagger2 使用初步
  2. 在CentOS上搭建最^1024基本的Nginx反向服务器
  3. 淘宝(阿里百川)手机客户端开发日记第十篇 阿里百川服务器环境介绍之API文档的快速链接(四)
  4. BZOJ-2324 营救皮卡丘 最小费用可行流+拆下界+Floyd预处理
  5. Windows7下安装搭建Ngnix教程
  6. 链接器工具错误 LNK2011
  7. spoj 1436
  8. STM32 IAP 在线更新程序 为什么有时行 有时又不行 感觉不可靠 问题解决
  9. 关于页面刷新或者调用方法事获取不到元素信息或者出现缺少对象错误的换位思考setTimeout的使用
  10. 使用Windows USB-DVD制作U盘启动安装系统盘
  11. 8.0 BOM对象
  12. HDU 1243 畅通project 并査集
  13. AOE 网络
  14. Mac OS X 终端命令开启功能
  15. abp中文件下载,将内存数据导出到Excel并下载
  16. typescript简介
  17. 【基础】在css中绘制三角形及相关应用
  18. Day 11 函数对象,函数嵌套,作用域,闭包
  19. 后端python基础
  20. STL常用容器使用方法

热门文章

  1. 修改hosts不必重启 立刻生效
  2. 编程英语之KNN算法
  3. reload(sys)后print失效问题解决
  4. kafka Centos7.2 单机集群搭建
  5. linux 3.10 缺页异常(TLB_invalid)通用处理框架
  6. Rstudio-server 重新登录载入session的问题
  7. R语言使用 multicore 包进行并行计算
  8. URL重定向漏洞,python打造URL重定向漏洞检测脚本
  9. 在Mac上搭建React Native开发环境
  10. Android Studio下多渠道打包