1.synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:

1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

2.synchronized的缺陷

synchronized是java中的一个关键字,也就是说是Java语言内置的特性。

如果一个代码块被synchronized修饰了,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况:

1)获取锁的线程执行完了该代码块,然后线程释放对锁的占有;

2)线程执行发生异常,此时JVM会让线程自动释放锁。

简单的东西没必要总结,我们来看其中的几个关键点,值得体会,用一个例子说话:

  1. 1 public class Demo4 {
  2. public static void main(String[] args) {
  3. final Output output = new Output();
  4. new Thread(new Runnable() {
  5.  
  6. @Override
  7. public void run() {
  8. while(true){
  9. try {
  10. Thread.sleep(500);
  11. } catch (InterruptedException e) {
  12. e.printStackTrace();
  13. }
  14. output.Output1("chenchi");
  15. }
  16. }
  17. }).start();
  18.  
  19. new Thread(new Runnable() {
  20.  
  21. @Override
  22. public void run() {
  23. while(true){
  24. try {
  25. Thread.sleep(500);
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. }
  29. output.Output1("sujunjun");
  30. }
  31. }
  32. }).start();
  33. }
  34.  
  35. static class Output {
  36. public void Output1(String name) {
  37. synchronized (this) {
  38. for (int i = 0; i < name.length(); i++) {
  39. System.out.print(name.charAt(i));
  40. }
  41. System.out.println();
  42. }
  43. }
  44.  
  45. public synchronized void Output2(String name) {
  46. for (int i = 0; i < name.length(); i++) {
  47. System.out.print(name.charAt(i));
  48. }
  49. System.out.println();
  50. }
  51.  
  52. public synchronized static void Output3(String name) {
  53. for (int i = 0; i < name.length(); i++) {
  54. System.out.print(name.charAt(i));
  55. }
  56. System.out.println();
  57. }
  58. }
  59. }

这个例子很简单,就是同时开启两个线程,声明一个Output内部类的对象,同时访问Output内部类的Output()方法。

1.

output.Output1("chenchi");

output.Output1("sujunjun");

很明显,打印中不会出现数据错误。synchronized ()只要保证括号里面是同一对象就不会产生错误。里面传的是this,由于两者对象都是output,所以加锁成功。

想一下,这样会成功吗?(可以)

  1.      String string = "";
  2. public void Output1(String name) {
  3. synchronized (string) {
  4. for (int i = 0; i < name.length(); i++) {
  5. System.out.print(name.charAt(i));
  6. }
  7. System.out.println();
  8. }
  9. }

这样呢?(可以)

  1. public void Output1(String name) {
  2. synchronized ("") {
  3. for (int i = 0; i < name.length(); i++) {
  4. System.out.print(name.charAt(i));
  5. }
  6. System.out.println();
  7. }
  8. }

这样呢?(不可以)

  1. public void Output1(String name) {
  2. synchronized (name) {
  3. for (int i = 0; i < name.length(); i++) {
  4. System.out.print(name.charAt(i));
  5. }
  6. System.out.println();
  7. }
  8. }

2.

output.Output1("chenchi");

output.Output2("sujunjun");

很明显,打印中不会出现错误,因为synchronized修饰方法就是相当于给方法加锁的是当前对象。

3.

output.Output1("chenchi");

output.Output3("sujunjun");

很明显,打印会出错。为什么呢?还是因为加锁对象不是同一个了。synchronized修饰静态方法后,上锁对象为当前类对象了。

什么是当前类对象呢?就是Class类型实例,JVM在加载任何一个类时,都会创建一个Class类型的实例描述该类,并且每个类有且只有一个Class的实例描述它。

如何同步?

  1. public void Output1(String name) {
  2. synchronized (Output.class) {
  3. for (int i = 0; i < name.length(); i++) {
  4. System.out.print(name.charAt(i));
  5. }
  6. System.out.println();
  7. }
  8. }

这里改了一下Output1方法,Output.class为上锁对象,就保证了同一对象。

多线程中的synchronized小结的更多相关文章

  1. 多线程中的synchronized

    synchronized是Java中的关键字,是一种同步锁.它修饰的对象有以下几种: 1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码 ...

  2. 多线程中的Lock小结

    出处:http://www.cnblogs.com/DarrenChan/p/6528578.html#undefined 1.lock和synchronized的区别 1)Lock不是Java语言内 ...

  3. java多线程中 volatile与synchronized的区别-阿里面试

    volatile 与 synchronized 的比较(阿里面试官问的问题) ①volatile轻量级,只能修饰变量.synchronized重量级,还可修饰方法 ②volatile只能保证数据的可见 ...

  4. [多线程] 线程中的synchronized关键字锁

    为什么要用锁? 在多线程中,难免会出现在多个线程中对同一个对象的实例变量或者全局静态变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实 ...

  5. java中多线程详解-synchronized

    一.介绍 当多个线程涉及到共享数据的时候,就会设计到线程安全的问题.非线程安全其实会在多个线程对同一个对象中的实例变量进行并发访问时发生,产生的后果就是“脏读”.发生脏读,就是取到的数据已经被其他的线 ...

  6. c#多线程中Lock()关键字的用法小结

    本篇文章主要是对c#多线程中Lock()关键字的用法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助     本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段 ...

  7. 深入理解java中的synchronized关键字

    synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D ...

  8. BlockingQueue阻塞队列(解决多线程中数据安全问题 可用于抢票,秒杀)

    案例:一个线程类中 private static BlockingQueue<Map<String, String>> dataQueue = new LinkedBlocki ...

  9. java中的synchronized同步代码块和同步方法的区别

    下面这两段代码有什么区别? //下列两个方法有什么区别 public synchronized void method1(){} public void method2(){ synchronized ...

随机推荐

  1. 有效Log4j按指定级别定向输出日志到指定的输出文件地址配置Threshold,log4j中如何屏蔽父logger输出源rootlogger的additivity配置,log4j向多个文件记录日志

    log4j向多个文件记录日志 关键配置,指定想要的日志级别信息输出到指定的日志文件中: log4j.appender.errorLogger.Threshold=ERROR #扩展,可指定只在子类自己 ...

  2. jsp地址栏传中文显示乱码解决方法

    格式一: 地址栏显示格式:http://localhost:8081/Jsp2/ahref2.jsp?id=32&name=%E7%8E%8B%E4%BA%91%E9%B9%8F 1.修改To ...

  3. FA_固定资产六大业务增加、修改、报废、在建、折旧、盘点概述(概念)

    2014-06-04 Created By BaoXinjian

  4. 共享内存简介和mmap 函数

    一.共享内存简介 共享内存区是最快的IPC形式,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据. 即每个进程地址空间都有一个共享存储器的映射区,当这块区 ...

  5. page_address()函数分析

    由于X86平台上面,内存是划分为低端内存和高端内存的,所以在两个区域内的page查找对应的虚拟地址是不一样的. 一. x86上关于page_address()函数的定义 在include/linux/ ...

  6. Concurrency Managed Workqueue(一)workqueue基本概念

    一.前言 workqueue是一个驱动工程师常用的工具,在旧的内核中(指2.6.36之前的内核版本)workqueue代码比较简单(大概800行),在2.6.36内核版本中引入了CMWQ(Concur ...

  7. Linux内核(4) - 内核学习的心理问题

    对于学习来说,无论是在学校的课堂学习,还是这里说的内核学习,效果好或者坏,最主要取决于两个方面——方法论和心理.注意,我无视了智商的差异,这玩意儿玄之又玄,岔开了说,属于迷信的范畴. 前面又是Kern ...

  8. Python lstrip() 方法

    描述 Python lstrip() 方法用于删除字符串头部指定的字符,默认字符为所有空字符,包括空格.换行(\n).制表符(\t)等. 语法 lstrip() 方法语法: S.lstrip([cha ...

  9. python标准库介绍——7 cmath 模块详解

    [Example 1-61 #eg-1-61] 所展示的 ``cmath`` 模块包含了一些用于复数运算的函数. ====Example 1-61. 使用 cmath 模块====[eg-1-61] ...

  10. PLSA-概率潜语义分析(二)

    PLSA最大化下面函数: 简化后,最大化下面函数: . ------------------------------------------------------------------------ ...