Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2019-03-15:如何实现多线程中的同步? #6

Open
Moosphan opened this issue Mar 15, 2019 · 18 comments
Open

2019-03-15:如何实现多线程中的同步? #6

Moosphan opened this issue Mar 15, 2019 · 18 comments
Labels

Comments

@Moosphan
Copy link
Owner

No description provided.

@Moosphan Moosphan added the underway the daily question is solving now label Mar 15, 2019
@ADrunkenLiBai
Copy link

NO 知啊

@ADrunkenLiBai
Copy link

多线程同步跟异步这不是两种事物吗,不是应该线程池跟线程锁吗

@Moosphan Moosphan added finished and removed underway the daily question is solving now labels Mar 20, 2019
@Alex-Cin
Copy link

Alex-Cin commented Mar 28, 2019

我了解到的, 大概是这样的几种方式:

  1. volatile-某种简单的逻辑下, 是可以的;
  2. synchronized;
  3. reentrantLock;
  4. cas=compare and swap(set), 就是 unsafe 类;
  5. handler(有点勉强, 他的实现本身依赖上面的一些技术)

@Ssuiyingsen 回答的, 和这个问题, 有点偏离, 不建议这样回答(重点在于解决同步问题, 不是怎么跑起来多个线程);

@Moosphan Moosphan added 线程 and removed finished labels Apr 11, 2019
@sukaidev
Copy link

线程同步:
1、wait/notify
2、加锁,reentrantLock 以及读写锁
3、synchronized关键字(本质也是加锁)
4、cas

@jmhjmh
Copy link

jmhjmh commented Apr 22, 2019

多线程同步和异步不是一回事。
几种情况,
1.就是大家说的synchronized 他可以保证原子性,保证多个线程在操作同一方法时只有一个线程可以持有锁,并且操作该方法,
2.就是手动调用读写锁,
3.手动操作线程的wait和notify
4. volatile我记得是没有原子性的,他可以保证内存可见性,在多线程的情况下保证每个线程的数据都是最新的

@risechen
Copy link

risechen commented May 7, 2019

线程间的同步实质是保证相城中共享变量的数据同步

  1. volatile关键字,在get和set的场景下是可以的,由于get和set的时候都加了读写内存屏障,在数据可见性上保证数据同步。但是对于++这种非原子性操作,数据会出现不同步
  2. synchronized对代码块或方法加锁,结合wait,notify调度保证数据同步
  3. reentrantLock加锁结合Condition条件设置,在线程调度上保障数据同步
  4. CountDownLatch简化版的条件锁,在线程调度上保障数据同步
  5. cas=compare and swap(set), 在保证操作原子性上,确保数据同步
  6. 参照UI线程更新UI的思路,使用handler把多线程的数据更新都集中在一个线程上,避免多线程出现脏读

@RedDargon
Copy link

可以用 synchronized 关键词 作用在代码块上 或者静态非静态方法都可以。
或者 wait/notifyAll。
参数可以加入 volatile参数 让其做到 内存可见性。

@BlockWen
Copy link

BlockWen commented Jul 5, 2019

多线程同步和异步不是一回事。
几种情况,
1.就是大家说的synchronized 他可以保证原子性,保证多个线程在操作同一方法时只有一个线程可以持有锁,并且操作该方法,
2.就是手动调用读写锁,
3.手动操作线程的wait和notify
4. volatile我记得是没有原子性的,他可以保证内存可见性,在多线程的情况下保证每个线程的数据都是最新的

volitile主要是在CPU指令禁止重排和多线程访问变量时变量发生变化时,各线程的值是同时变化的。

@LineCutFeng
Copy link

更多的情况下,如果仅仅是一个变量的同步性,我喜欢原子类AtomicInteger AtomicBoolean等等,这样写还简单

@ZHANGfeng-james
Copy link

@3shenze
Copy link

3shenze commented Aug 15, 2019

thread.join也算吗

@xinyu618
Copy link

多线程下的线程同步,保证代码在多线程下实现 原子性 可见性 有序性
1、volatile 确保了可见性、有序性,但不能保证原子性 对于++这种操作就不能保证同步
2、synchronized 保证了可见性 有序性和原子性

@micadalee
Copy link

1.继承Thread类,重写run函数方法
2.实现Runnable接口,重写run函数方法
3.实现Callable接口,重写call函数方法
4.HandlerThread
5.AsyncTask很老的一种= =
6.Synchronized 同步

只有6是正确的,其他都是如何异步

@gabyallen
Copy link

1.继承线程类,重构运行函数方法
2.实现Runnable接口,重构运行函数方法
3.实现Callable接口,调用调用函数方法
4.HandlerThread
5.AsyncTask很老的一种= =
6.同步同步

@feelschaotic
Copy link

  1. 只有一个线程写,其他都是读,用 volatile
  2. 多个线程写,用 Synchronized
  3. 多个线程写+设置超时+自行决定释放,用 ReentranLock
  4. 提高效率,不单单一个线程进入临界区,用并发包,如:ConcurrentHashMap、LinkBlockingQueue、AtomicXXX。
  5. 读比写多,用 CopyOnWriteXXX
  6. 希望控制线程的并发数量,用 Semaphore 信号量
  7. 想让指定线程等待其他线程,用 CountDownLatch

@ryanlijianchang
Copy link

占坑

@treasure-lau
Copy link

  1. 同步方法
  2. 同步代码块
  3. 使用重入锁实现线程同步(ReentrantLock)
  4. 使用特殊域变量(volatile)实现同步(每次重新计算,安全但并非一致)
  5. 使用局部变量实现线程同步(ThreadLocal)以空间换时间
  6. 使用原子变量实现线程同步(AtomicInteger(乐观锁))
  7. 使用阻塞队列实现线程同步(BlockingQueue (常用)add(),offer(),put()
    参考链接:https://www.cnblogs.com/cxxjohnson/p/8536257.html

Repository owner deleted a comment from Ssuiyingsen Mar 5, 2020
@Jmengfei
Copy link

Jmengfei commented Mar 29, 2021

Java里面进行多线程通讯的主要方式就是共享内存的方式,共享内存主要关注的点有两个:可见有序原子性。Java的内存模型解决了可见性和有序性的问题,而锁解决的是原子性的问题。理想情况下我们希望做到**"同步""互斥"**。主要通过以下几种方式:

  • synchronized: 一般的做法是把修改共享变量的方法加上synchronized。
  • volatile:使用特殊域变量实现同步。volatile禁止了指令的重排序和变量可见性,只针对单次有效。类似i++的话是两次计算,所以无效。这是一种稍弱的同步机制。比synchronized更轻量级
  • ReentrantLock:显示的获得,释放锁,灵活度高。是同步非阻塞,采用的是乐观并发策略。可以简单理解为synchronized的灵活版本。synchronized是同步阻塞, 采用的是悲观并发策略。
  • Semaphore:信号量-控制同时访问的线程数量。这个也可以形成同步机制,一般用于控制对某组资源的访问权限。
  • BlockingQueue:阻塞队列。也是实现的一种,他有很多实现类,例如ArrayBlockingQueue, LinkedBlockingQueue, PriorityBlockingQueue...
    网上有很多说ThreadLocal可以实现,其实是有偏差的。ThreadLocal是给每一个线程都复制了一个副本到ThreadLocalMap中,各自互不干扰。因为操作的是各自不同的对象,所以不存在同步的问题。ThreadLocal隔离了多个线程的数据共享, 从根本上它是不存在数据共享的,也就不需要同步机制了。但是不可否认它是解决线程安全的很好的思路。

如果需要进行多个线程之间进行通信,则使用同步机制;
如果需要隔离多个线程之间的共享冲突,可以使用threadLocal。这会极大的简化程序,使程序更加易读、简洁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests