返回「计算机、信息技术与工程」

Unity Jobsystem问题

更多
Markdown 结构化数据
本文目录 3 个章节

Unity Jobsystem问题

note · 我的 UWA 问答 本文收录我在 UWA 问答发表的公开回答。问题内容归原提问者;回答保留当时语境,技术结论可能受 Unity 版本、平台和项目条件限制。

问题

using CSharp;

using Unity.Burst;

using Unity.Collections.LowLevel.Unsafe;

using UnityEngine;

using UnityEngine.Jobs;

using Unity.Collections;

using Unity.Jobs;

public class JobTest : MonoBehaviour

{

    // Start is called before the first frame update

    public Transform t1;

    public Transform t2;

    public TransformAccessArray TransformAccessArray;

    void Start()

    {

        TransformAccessArray = new TransformAccessArray(50000,64);

    }

    private JobHandle handle;

    // Update is called once per frame

    void Update()

    {

        if (!handle.IsCompleted)

        {

            return;

        }

        if (TransformAccessArray.length == 0)

        {

            TransformAccessArray.Add(t1);

            TransformAccessArray.Add(t2);

        }

        float t = Time.time;

        Debug.Log("time:" + t);

        NativeList<int> end_list = new NativeList<int>(TransformAccessArray.length,Allocator.TempJob);

        NativeList<int> end_id_list = new NativeList<int>(TransformAccessArray.length,Allocator.TempJob);

        UpdateJob job = new UpdateJob

        {

            time = t,

            end_list = end_list,

            end_id_list = end_id_list,

        };

        handle = job.Schedule(TransformAccessArray);

        handle.Complete();

        if (end_id_list.Length != end_list.Length)

        {

            Debug.LogError("error time:" + t);

        }

        else

        {

            Debug.LogWarning("right time:" + t);

        }

        end_list.Dispose();

        end_id_list.Dispose();

    }

}

using System;

using Unity.Burst;

using Unity.Collections;

using Unity.Collections.LowLevel.Unsafe;

using UnityEngine;

using UnityEngine.Jobs;

namespace CSharp

{

    [BurstCompile]

    public struct UpdateJob : IJobParallelForTransform

    {

        [NativeDisableContainerSafetyRestriction] public NativeList<int> end_list;

        [NativeDisableContainerSafetyRestriction] public NativeList<int> end_id_list;

        [ReadOnly] public float time;

        public void Execute(int index, TransformAccess transform)

        {

            end_list.Add(index);

            end_id_list.Add(index);

            int a = end_list.Length;

            int b = end_id_list.Length;

        }

    }

}

执行多线程之后发现,endidlist.Length和 end_list.Length的长度有时候不一样,谁能解答一下

  • 提问者:hardy
  • 提问时间:2021-03-09 22:55:15

我的回答

这样写的话,两个线程是并行的,并且是线程不安全的:

image.png

两个线程对指令的执行的先后顺序是不确定的。

如果两个线程依次对endlist进行Add的话,endlist就会加入两个元素。

如果两个线程同时取得end_list,同时进行Add,就会产生错误——两个线程都执行完后,某个List只添加了一个元素。

可以用如下方法进行验证:

image.png

image.png

如果对数据的访问进行加锁,保证一个线程访问list时,另外一个线程无法访问,就不会出现题主所述的问题。不过这多线程执行就没有意义了,相当于顺序执行。

  • 回答时间:2021-03-10 02:06:15
  • 最后更新:2021-03-10 02:07:28
  • 采纳状态:未采纳

来源与关系