【发布时间】:2021-11-21 06:13:35
【问题描述】:
我遇到了这个问题。
我有(至少)6 个协程,它们在通过互斥锁管理的地图上工作。
有时我需要在不同的场景中取消一个、多个或所有协程。
取消协程时处理互斥锁的最佳方法是什么? (事实是我真的不知道取消协程是否是锁定互斥锁的协程)。互斥体“系统”有什么巧妙的技巧来解决这个问题吗?
2021.09.30 11:28 GMT+2 (DST)
我的编码相当复杂,所以我将其简化并在这里展示主要问题
...
class HomeFragment:Fragment(){
...
private lateinit var googleMap:GoogleMap
val mapMutex = Mutex()
...
override fun onViewCreated(view:View, savedInstanceState: Bundle?) {
...
binding.fragmentHomeMapView?.geMapAsync { _googleMap ->
_googleMap?.let{ safeGoogleMap ->
googleMap = safeGoogleMap
}?:let{
Message.error("Error creating map (null)")
}
...
homeViewModel.apply {
...
//observer & coroutine 1
liveDataMapFlagged?.observe(
viewLifeCycleOwner
){flaggedMapDetailResult->
//Here I want to stop the lifecycleScope job below if it is already
//running and do some cleanup before entering (do I need to access the
//mutex if cleanup influence the google map ?)
//If I cancel the job, will the mutex then unlock gracefully ?
flaggedMapDetailResult?.apply {
...
lifecycleScope.launchWhenStarted { //Here I want to catch the job with i.e 'flagJob = lifeCycleScope.launchWhe...'
...
withContext(Dispatchers.Default){
...
mapMutex.withLock { //suspends if locked
withContext(Dispatchers.Main){
selectedSiteMarker?.remove()
selectedCircle?.remove()
... // Doing some cleanup... removing markers
}
... // Creating new markers
var flaggedSiteMarkerLatLng = coordinateSiteLatitude?.let safeLatitude@{safeLatitude->
return@safeLatitude coordinateSiteLongitude?.let safeLongitude@{safeLongitude->
return@safeLongitude LatLng(safeLatitude,safeLongitude)
}
}
...
flaggedSiteMarkerLatLng?.let { safeFlaggedSiteMarkerLatLng ->
val selectedSiteOptions =
MarkerOptions()
.position(safeFlaggedSiteMarkerLatLng)
.anchor(0.5f,0.5f)
.visible(flaggedMarkerState)
.flat(true)
.zIndex(10f)
.title(setTicketNumber(ticketNumber))
.snippet(appointmentName?:"Name is missing")
.icon(vSelectedSiteIcon)
selectedSiteMarker = withContext(Dispatchers.Main){
googleMap.addMarker(selectedSiteOptions)?.also{
it.tag = siteId
}
}
... //Do some more adding
} //End mutex
...
}//End dispatchers default
...
}//End lifecycleScope.launchWhenStarted
...
}?:let{//End apply
...//Cleanup if no data present
lifeCycleScope.launchWhenStarted{ //Shoud harvest Job and stop above
//if it is called before ending...
//if necessary
mapMutex.withLock{
//Cleanup markers
}
}
}
...
}//End observer 1
//observer 2
liveDataMapListFromFiltered2?.observer(
viewLifeCycleOwner
){mapDetailList ->
//Should check if job below is running and cancel gracefully and
//clean up data
...//Do some work on mapDetailList and create new datasets
lifecycleScope.launchWhenStarted{ //Scope start (should harvest job)
...
withContext(Dispatchers.Default) //Default context
{
...//Do some heavy work on list (no need for mutex)
}
mapMutex.withLock {
withContext(Dispatchers.Main)
{
//Do work on googlemap. Move camera etc.
}
}
...//Do other not map related work
mapMutex.withLock {
withContext(Dispatchers.Main)
{
//Do work on googlemap. Move camera etc.
}
}
...//Do other not map related work
mapMutex.withLock {
withContext(Dispatchers.Main)
{
//Do work on googlemap. Move camera etc.
}
}//end mutex
}//end scope
}//end observer 2
}//end viewmode
}//end gogleMap
【问题讨论】:
-
您对取消和互斥有什么顾虑?您是否担心取消当前持有锁的协程后,它不会被正确释放?或者取消会发生在修改一些数据的过程中,所以可能会留下不一致的状态?
-
我管理的数据的一致性,但是互斥锁是否被我正在取消的协程锁定的事实更糟。
-
我刚刚添加了代码场景,其中问题显示了 3 个主要的协程场景。