如何在给定代码的lambda表达式中添加同步?synchronized块是否适用?
问题解答
1. lambda表达式内能否使用synchronized块?
完全可以。lambda表达式只是Java中函数式接口的简化实现语法,内部的代码块和普通类方法中的代码逻辑没有语法限制,完全支持synchronized同步块、锁等所有常规并发控制手段。
2. 同步机制添加方案
你可以根据需要选择加锁的粒度,通常我们会选择共享变量list作为锁对象,保证读写操作的原子性:
方案1:给整个lambda的执行逻辑加锁
{ List<Integer> list = new ArrayList<>(10000); IntStream.range(1, 10000).forEach(list::add); Thread reader = new Thread(() -> { // 以共享集合list作为锁对象 synchronized (list) { list.forEach(i -> System.out.println("r " + i)); } }, "t1"); }
方案2:给forEach内部的元素消费逻辑加锁(更小粒度)
如果你只需要保证每次打印操作的原子性,可以把synchronized块写在内部的lambda里:
Thread reader = new Thread(() -> { list.forEach(i -> { synchronized (list) { System.out.println("r " + i); } }); }, "t1");
注意事项
- 锁对象必须是所有读写线程共享的对象,这里用
list本身是合理的,因为它是多线程共同操作的共享资源 - 你当前给出的代码片段中,
list的写入操作都在主线程完成,之后才启动读线程,本身不存在并发冲突,但如果后续有其他线程同时修改list,所有读写操作都需要加同一把锁,否则同步不生效 - 也可以用
java.util.concurrent.locks包下的显式锁实现同步,逻辑和synchronized是一致的
内容的提问来源于stack exchange,提问作者Tanmay Mandaogane
相关产品推荐
相关产品推荐

