多线程中的synchronized
1.synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
2.synchronized的缺陷
synchronized是java中的一个关键字,也就是说是Java语言内置的特性。
如果一个代码块被synchronized修饰了,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况:
1)获取锁的线程执行完了该代码块,然后线程释放对锁的占有;
2)线程执行发生异常,此时JVM会让线程自动释放锁。
简单的东西没必要总结,我们来看其中的几个关键点,值得体会,用一个例子说话:
1 public class Demo4 {
public static void main(String[] args) {
final Output output = new Output();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
output.Output1("chenchi");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
output.Output1("sujunjun");
}
}
}).start();
}
static class Output {
public void Output1(String name) {
synchronized (this) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
public synchronized void Output2(String name) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
public synchronized static void Output3(String name) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
这个例子很简单,就是同时开启两个线程,声明一个Output内部类的对象,同时访问Output内部类的Output()方法。
1.
output.Output1("chenchi");
output.Output1("sujunjun");
很明显,打印中不会出现数据错误。synchronized ()只要保证括号里面是同一对象就不会产生错误。里面传的是this,由于两者对象都是output,所以加锁成功。
想一下,这样会成功吗?(可以)
String string = "";
public void Output1(String name) {
synchronized (string) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
这样呢?(可以)
public void Output1(String name) {
synchronized ("") {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
这样呢?(不可以)
public void Output1(String name) {
synchronized (name) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
2.
output.Output1("chenchi");
output.Output2("sujunjun");
很明显,打印中不会出现错误,因为synchronized修饰方法就是相当于给方法加锁的是当前对象。
3.
output.Output1("chenchi");
output.Output3("sujunjun");
很明显,打印会出错。为什么呢?还是因为加锁对象不是同一个了。synchronized修饰静态方法后,上锁对象为当前类对象了。
什么是当前类对象呢?就是Class类型实例,JVM在加载任何一个类时,都会创建一个Class类型的实例描述该类,并且每个类有且只有一个Class的实例描述它。
如何同步?
public void Output1(String name) {
synchronized (Output.class) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
这里改了一下Output1方法,Output.class为上锁对象,就保证了同一对象。
多线程中的synchronized的更多相关文章
- 多线程中的synchronized小结
1.synchronized是Java中的关键字,是一种同步锁.它修饰的对象有以下几种: 1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个 ...
- java多线程中 volatile与synchronized的区别-阿里面试
volatile 与 synchronized 的比较(阿里面试官问的问题) ①volatile轻量级,只能修饰变量.synchronized重量级,还可修饰方法 ②volatile只能保证数据的可见 ...
- [多线程] 线程中的synchronized关键字锁
为什么要用锁? 在多线程中,难免会出现在多个线程中对同一个对象的实例变量或者全局静态变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实 ...
- java中多线程详解-synchronized
一.介绍 当多个线程涉及到共享数据的时候,就会设计到线程安全的问题.非线程安全其实会在多个线程对同一个对象中的实例变量进行并发访问时发生,产生的后果就是“脏读”.发生脏读,就是取到的数据已经被其他的线 ...
- Java多线程4:synchronized锁机制
脏读 一个常见的概念.在多线程中,难免会出现在多个线程中对同一个对象的实例变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实是被更改过 ...
- c#初学-多线程中lock用法的经典实例
本文转载自:http://www.cnblogs.com/promise-7/articles/2354077.html 一.Lock定义 lock 关键字可以用来确保代码块完成运行,而不会被 ...
- 深入理解java中的synchronized关键字
synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D ...
- Java多线程4:synchronized关键字
原文:http://www.cnblogs.com/skywang12345/p/3479202.html 1. synchronized原理在java中,每一个对象有且仅有一个同步锁.这也意味着,同 ...
- java中的synchronized关键字
参考:http://www.cnblogs.com/devinzhang/archive/2011/12/14/2287675.html 多线程并发问题的根因: 在一个对象中有一个变量i=0,有两个线 ...
随机推荐
- poj1416 Shredding Company
Shredding Company Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 5379 Accepted: 3023 ...
- Android的4种文件类型Java,class,dex,apk
Java文件-----应用程序源文件 Android本身相当一部分都是用java编写而成(基本上架构图里头蓝色的部份都是用Java开发的),android的应用必须使用java来开发 Class文件- ...
- Samsung I9103刷cm-10.1的方法
按照官方网站的说明一步一步的做下去的时候发现在执行heimdall.exe文件的时候出现“不是win32的应用程序”的错误提示,因此决定按照其它方法安装recovery,然后再刷入CM10.1. sa ...
- 小Y的棋盘问题 题解
有一个n*m的棋盘,上面有一些棋子,每行每列最多只会有一个棋子,不会有两个棋子八连通.问随机一个空格子作为起点,再随机地选择一个空格子作为终点,求问不经过任意棋子最短路的期望长度是多少.多组,n,m& ...
- CoreAnimation笔记
核心动画继承结构 CoreAnimation Core Animation是直接作用在CALayer上的(并非UIView上)非常强大的跨Mac OS X和iOS平台的动画处理API,Core Ani ...
- 添加Distributor失败
上周做了一个case,客户无法为SQL Server instance配置remote distributor. 下面分享一下排查问题的过程,希望对您排查类似的问题所有帮助. 客户的环境中的SQL S ...
- Exchange WebSerivce Usage
//ExchangeService版本为2007SP1 ExchangeService service = new ExchangeService(ExchangeVersion.Exchange20 ...
- [转]一篇很全面的freemarker教程
copy自http://demojava.iteye.com/blog/800204 以下内容全部是网上收集: FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主 ...
- weblogic启动失败:Could not obtain the localhost address 解决办法
linux下weblogic启动如果出现这个错误,多半是hosts文件不对 1.先输入hostname,查看本机计算机名(比如:server123) 2.sudo vi /etc/hosts 编辑ho ...
- Theano2.1.10-基础知识之循环
来自:http://deeplearning.net/software/theano/tutorial/loop.html loop 一.Scan 一个递归的通常的形式,可以用来作为循环语句. 约间和 ...